Webpack 5 环境变量注入实战:DefinePlugin、--env 与 cross-env

作者:望舒

时间:2026-10-24

浏览:390

本文详解 Webpack 中环境变量的三种注入方式。首先解析 DefinePlugin 通过字符串替换实现业务代码全局变量注入,强调 JSON.stringify 的必要性;其次介绍利用 --env 参数配合 module.exports 函数在构建配置中获取变量;最后演示使用 cross-env 插件绕过限制,通过 process.env 直接访问传统环境变量。

文章目录

前言

你是否曾因 Webpack 复杂的打包配置而感到困扰?

本文将深入探讨在 Webpack 中注入环境变量的多种实现方式。或许你会认为,仅通过命令行注入环境变量即可满足需求,但继续阅读后,你将发现更多实用的技巧。

保持耐心阅读,相信你会获得新的启发。

成长源于点滴积累,接下来我们将详细解析在 Webpack 5 中正确注入环境变量的几种方法。

文章将从以下三个维度讲解 Webpack 流程中的环境变量应用:

  • 在业务代码中注入并使用 Webpack 环境变量。
  • 利用 Webpack 官方提供的构建过程环境变量机制。
  • 通过传统环境变量方法配合 Webpack 构建过程进行注入。

业务代码中的环境变量使用

利用 webpack.DefinePlugin 插件在业务代码中注入环境变量

许多开发者已熟悉此场景:在打包过程中通过 Webpack 注入全局变量,供业务代码直接使用。例如,业务入口文件中包含如下代码:


// src/main.js
console.log('hello, Environment variable', __WEPBACK__ENV)

我们期望当业务代码中引用 __WEBPACK__ENV 变量时,能够识别该变量并输出正确的字符串值 'packages'。

我们该如何实现这一目标?

熟悉 Webpack 的开发者可能已经想到,可以通过 webpack 中的 DefinePlugin 插件进行注入:


const wepback = require('webpack')
// webpack.config.js
...
new webpack.DefinePlugin({
  __WEBPACK__ENV: JSON.stringify('packages'),
  TWO: '1+1',
});

在 Webpack 的 plugins 配置中添加上述代码后,运行打包命令。此时,若业务代码中出现 __WEBPACK__ENV 变量,Webpack 会将其替换为字符串 'packages',从而实现类似环境变量的注入效果。

对 webpack.DefinePlugin 的深入思考

或许你对 DefinePlugin 的使用已非常熟练,但请继续向下阅读,这段代码引出了以下几个值得思考的问题:

  1. 'packages' 已是字符串类型,为何还需使用 JSON.stringify() 进行处理?
  2. 这种注入方式生成的真的是传统意义上的环境变量吗?

我们先来探讨这两个问题:

DefinePlugin 所谓的“环境变量”实现原理

Webpack 官方文档中对此有明确说明:

(Note that because the plugin does a direct text replacement, the value given to it must include actual quotes inside of the string itself. Typically, this is done either with alternate quotes, such as '"production"', or by using JSON.stringify('production').)

这表明 DefinePlugin 的本质是在打包过程中进行字符串替换。例如,我们定义 __WEBPACK__ENV: JSON.stringify('packages')。

在打包过程中,若代码中使用了 __WEPBACK__ENV,Webpack 会将其值替换为 DefinePlugin 中定义的值。这本质上是匹配字符串替换,而非传统意义上的 process 环境变量注入。

这也就回答了第二个问题。

关于 JSON.stringify() 处理环境变量的必要性

接下来探讨第一个问题,实践出真知。我们对比两次不同的 DefinePlugin 配置来看看结果:


// webpack.config.js
new webpack.DefinePlugin({
  __WEBPACK__ENV: JSON.stringify('packages'),
  TWO: '1+1',
});

// 打包后的代码 这里我们关闭了devtools 罗列出打包后打包后的代码
console.log('hello, Environment variable', 'packages')

// webpack.config.js
new webpack.DefinePlugin({
  __WEBPACK__ENV: 'packages',
  TWO: '1+1',
});

// 打包后的代码 这里我们关闭了devtools 罗列出打包后打包后的代码
console.log('hello, Environment variable', packages)

仔细对比这两段代码,第一个问题的答案已显而易见。针对 DefinePlugin 插件,定义 key:value 全局变量时,它会将 value 直接替换为文本。因此,我们通常使用 JSON.stringify('packages') 或 "'packages'"。

关于 DefinePlugin 的流程及需注意的细节已阐述清楚,但此时定义的全局变量仅在业务代码中使用。若想在打包构建过程中使用环境变量,则需要另一种注入方式。

构建过程中的环境变量使用

通常在使用 Webpack 时,我们需要根据独特需求通过环境变量进行动态打包,例如动态读取项目文件夹,并在控制台与用户交互以打包不同的 bundle。

此时,在构建过程中使用环境变量显得尤为重要。所谓构建过程中使用环境变量,简单来说,就是在非业务代码(如 webpack.config.js 配置文件)中注入环境变量。

我们在项目中输入以下命令:


npx webpack --env goal=local --env production --progress --config ./webpack.config.js

该命令相当于运行 Webpack 读取当前目录中的 webpack.config.js 配置文件进行打包,同时注入两个环境变量 goal 和 production,其值分别为 'local' 和 true。

这样我们就可以在配置文件中利用注入的环境变量:


const path = require('path');

module.exports = (env) => {
  // Use env.<YOUR VARIABLE> here:
  console.log('Goal: ', env.goal); // 'local'
  console.log('Production: ', env.production); // true

  return {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist'),
    },
  };
};

细心的读者可能已发现,这里 module.exports 导出的是一个包含 env 参数的函数,而非传统的对象。

通常,module.exports 指向配置对象。要使用 env 变量,必须将 module.exports 转换为函数形式。我们来看看不使用函数的情况:


const path = require('path');

// Use env.<YOUR VARIABLE> here:
console.log('Goal: ', process.env.goal); // undefined
console.log('Production: ', process.env.production); // undefined

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
};

我们可以看到,从 node 进程的 process.env 中读取 goal 和 production 时,两者的值均为 undefined。

这意味着,通常在使用 --env 命令行参数为 Webpack 构建过程注入环境变量时,需要将配置文件的 module.exports 导出为一个函数,从而在函数的第一个参数中获取对应的 key 及环境变量 value。

那么问题来了,假如我就是想在 node 的 process 中获取对应的环境变量呢?我不想写函数,该怎么办?

传统环境变量方法在 Webpack 构建过程中的应用

该如何解决?其实 Webpack 打包的原理是通过 shell 命令执行我们的配置文件(Node.js 配置文件)。

如果在运行 webpack 命令时注入真正传统意义上的环境变量,而非通过 --env 参数,是否可行?接下来我们尝试一下:

这里借助了一个非常实用的环境变量插件 cross-env。它的使用方式简单,能帮助我们在 Linux/Windows 等不同环境下以相同方式注入运行时环境变量。接下来我们使用它:

不要忘记安装 npm install --save-dev cross-env。


// package.json
 "build": "cross-env NAME_W=aaa webpack --config ./webpack.config.js"

我们通过 cross-env NAME_W=aaa 注入了一个环境变量。


// webpack.config.js
console.log(process.env.NAME_W, 'env'); // 'aaa'

module.exports = {
  entry: './src/a.js',
};

经过尝试,我们发现通过命令行传统方式注入环境变量也是可行的!这样我们就摆脱了必须导出函数的限制,可以“为所欲为”了。

总结

在 Webpack 构建及业务代码中,环境变量的注入对我们的帮助巨大。当需要体系化的前端工程化代码时,环境变量无论是在构建过程还是业务代码中都起到了至关重要的作用。

至此,我们要讲的内容已全部涵盖,下面进行简单总结:

在 Webpack 打包业务代码时,若需以类似环境变量的方式使用全局变量,可通过 webpack.DefinePlugin 定义变量供业务代码使用(但需注意前文提到的 JSON.stringify() 问题)。

同时在构建过程中,我们可以通过 Webpack 官方提供的 --env 参数,以及在配置文件中通过 module.exports 函数的方式使用 --env 定义的环境变量。

此外,在构建过程中,我们还可通过日常使用的方式注入环境变量,从而“逃脱” Webpack 的限制,直接使用命令行中定义的环境变量,并通过 process.env.xxx 获取。

到此,关于 Webpack 中使用环境变量的文章介绍完毕。更多相关 Webpack 使用环境变量内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章