有些时候我们希望某些代码只在特定环境中能够执行。前面讲到,代码压缩工具会将死代码(if(false)
)删除,因此,我们可以基于这个特性,通过 DefinePlugin
定义一些环境变量,来将类似
if (process.env.NODE_ENV === "development") {
console.log("Hello during development");
}
2
3
这样的代码转换成 if(true)
或者 if(false)
的形式。
从 Webpack 4 开始,process.env.NODE_ENV
默认根据 mode
参数设置,但是仅限于 Webpack 内部。如果想要将 process.env.NODE_ENV
传给给其他工具,则需要在 Webpack 外或者在 Webpack 配置文件中定义。
除了使用
process.env.NODE_ENV
, 我们还可以通过webpack.EnvironmentPlugin(["NODE_ENV"])
读取环境变量,底层基于DefinePlugin
。
dotenv-webpackopen in new window 从一个
.env
文件中读取配置,然后内部使用DefinePlugin
来定义环境变量。
DefinePlugin
的基础用法
有下面这段代码:
var foo;
if (foo === 'bar') console.log('bar'); // Not free
if (bar === 'bar') console.log('bar'); // Free
2
3
如果将 bar
替换成字符串 "foobar"
,则代码如下:
var foo;
if (foo === 'bar') console.log('bar'); // Not free
if ('foobar' === 'bar') console.log('bar');
2
3
在进行代码压缩的时候,通过代码分析,上面的代码与下面这段等价:
var foo;
if (foo === 'bar') console.log('bar'); // Not free
if (false) console.log('bar');
2
3
则最终生成代码为:
var foo;
if (foo === 'bar') console.log('bar'); // Not free
2
基于条件的删除代码是 DefinePlugin
的核心能力。代码压缩器会分析代码,并将无用代码完全删除。
在 Babel 中,babel-plugin-transform-defineopen in new window 有着同样的功能。
process .env.NODE_ENV
设置 因为 Webpack 是直接替换变量文本,因此在定义环境变量值的时候,我们需要 JSON.stringify
一下。此时,环境变量的值为 "demo"
,然后 Webpack 会逐个替换找到的文本。
webpack.parts.js
exports.setFreeVariable = (key, value) => {
const env = {};
env[key] = JSON.stringify(value);
return {
plugins: [new webpack.DefinePlugin(env)],
};
};
2
3
4
5
6
7
8
webpack.config.js
const commonConfig = merge([
...parts.setFreeVariable('HELLO', 'hello from config'),
]);
2
3
在应用代码中:
src/component.js
// export default (text = "Hello world") => {
export default (text = HELLO) => {
const element = document.createElement("div");
...
};
2
3
4
5
6
此时运行代码,可以看到按钮的文案发生了变化。
根据环境变量加载不同的模块
我们可以借助于 DefinePlugin
来有条件的加载某些模块。比如有如下代码:
.
└── store
├── index.js
├── store.dev.js
└── store.prod.js
2
3
4
5
在 index.js
中:
if (process.env.NODE_ENV === 'production') {
module.exports = require('./store.prod');
} else {
module.exports = require('./store.dev');
}
2
3
4
5
此时,我们通过 DefinePlugin
定义 NODE_ENV
来加载不同的模块。值得注意的是,这里只能使用 CommonJS 模块语法,因为 ES2015 不支持动态导入模块。
总结
Webpack 可以通过 DefinePlugin
和 EnvironmentPlugin
来定义环境变量。EnvironmentPlugin
同时还会将系统环境变量也添加进来。
DefinePlugin
会基于 Webpack 的分析进行自由变量替换。在 Babel 中也有类似的功能。
一些代码压缩工具会将死代码删除,因此我们可以借助于 DefinePlugin
来生成死代码,从而将这些代码从构建输出结果中删除。
DefinePlugin
还可以被应用在模块级别,通过一个包装函数,我们可以有条件的决定使用哪个模块。
关注微信公众号,获取最新推送~
加微信,深入交流~