项目上线的时候一般要把 JS 和 CSS 压缩一下,用 webpack 的 uglifyJSPlugin 和 css-loader 的 minimize 选项可以分别压缩 JS 和 CSS. 但是偶然发现一个项目里的 CSS 并没有被压缩。最后发现是一个环境变量在不同的系统下不统一的锅。
通过为 css-loader 指定参数,可以在打包的时候压缩 CSS 样式文件。例如:
{
test: /(\.styl)$/,
loaders: [
'style-loader',
{
loader: 'css-loader',
options: {
minimize: process.env.NODE_ENV === 'production'
}
}
'postcss-loader',
'stylus-loader'
]
}
因为个人习惯,我一般不把 minimize
属性直接设置为 true,而是判断当前是否将要打包成生产环境用的文件,如果是才压缩 CSS. 然而就在这个地方出了锅,发现弄出来的 CSS 根本没压缩。一开始以为是 ExtractTextPlugin 的问题,后来发现如果直接把 minimize 的值设置为 true 的时候就会压缩,那么问题就在于 process.env.NODE_ENV === 'production'
表达式返回了不正确的值。
导致这个原因的问题在于没有设置 NODE_ENV
环境变量= =这个变量需要在运行 webpack 的时候设置,之前一直以为使用 webpack.DefinePlugin
定义 process.env.NODE_ENV
就可以的:
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
})
猜测 webpack.DefinePlugin
插件定义的变量只对项目的代码有效(就是对要打包的目标生效),但是对打包工具 webpack 自身似乎是无效的,所以即便在项目中 process.env.NODE_ENV
能取到正常的值,但是对于其他情况下 process.env.NODE_ENV
就没有定义了。
解决方法就是手动在终端中定义 process.env.NODE_ENV
变量,但是这样太麻烦了,而且还有跨系统兼容性的问题。可以使用 cross-env 来定义环境变量,然后再通过其启动 webpack.
yarn add --dev cross-env
然后修改 package.json
中的 script
字段,在执行打包命令的时候先调用 cross-env 设置环境变量,然后再唤起 webpack. 例如:
"scripts": {
"dist": "cross-env NODE_ENV=production webpack --config config/webpack.config.js --env=production",
"serve": "cross-env NODE_ENV=dev webpack-dev-server --progress --config config/webpack.config.js --env=dev",
"serve:dist": "cross-env NODE_ENV=dist wepack-dev-server --progress --config config/webpack.config.js --env=production",
"watch": "cross-env NODE_ENV=dev webpack --progress --watch --config config/webpack.config.js --env=dev"
},
这样子再运行打包生产环境文件的命令的时候,webpack 就能获取到正确的 process.env.NODE_ENV
环境变量,就能正常压缩 CSS 了。