blog
blog copied to clipboard
重新认识 Webpack 的 optimization.minimizer
我有一个项目的 Webpack 配置,里面有且仅有一个 CopyWebpackPlugin,我用它复制了一些 js / css 文件到 dist 文件夹,同时,我使用了 CopyWebpackPlugin 的 transform 选项来压缩这些文件。
我的配置大概是这样:
// webpack.config.js
const CopyPlugin = require('copy-webpack-plugin')
const Terser = require('terser')
const CleanCSS = require('clean-css')
module.exports = {
mode: 'production',
plugin: [
new CopyPlugin({
patterns: [
{
from: '**/*.js'
async transform (content) {
return await Terser.minify(content.toString())).code
}
},
{
from: '**/*.css'
async transform (content) {
return await new CleanCSS().minify(content.toString()).styles
}
},
]
})
]
}
这些文件来自第三方,我会定期更新它。今天,我更新了这些文件,然后报错了:
Terser: Unexpected token name «import», expected punc «,» [path/to/source.js:10,46]
我发现 path/to/source.js:10,46 现在多了一条 await import('...') 语句,这个问题好解决,只需要给 Terser 加个选项 module: true 就可以了。完成之后,我又试了下,结果仍然报错了:
ERROR in path/to/source.js
path/to/source.js from Terser plugin
Unexpected token name «import», expected punc «,» [path/to/source.js:10,46]
我一开始以为是我的 Terser 配置有问题,以为还需要加些别的什么配置。我翻遍了 Terser 的文档,都没有看出个所以然,而最后我突然注意到两次报错的内容不一样,后者的错误信息 from Terser plugin
这就奇怪了——我并没有给我的 Webpack 添加 TerserWebpackPlugin。
难道 Webpack 在 production 模式下,会自动使用 TerserPlugin 吗?
这一点在文档里 https://webpack.js.org/configuration/mode/ 得到了确认,Webpack 确实会在 production 模式下启用 TerserPlugin(以及其它一些插件),但是我又有疑问了:由 CopyPlugin 复制的文件并不是 entry 引用的,难道 TerserPlugin 对 entry 外的文件也会起作用吗?
看了下 TerserPlugin 的文档,我发现它虽然是 Webpack 插件,但是它却不是声明在 plugins 里,而是在 optimization.minimizer,所以我又有了一个猜想:难道是 optimization.minimizer 里会对 entry 以外的文件生效?
为了验证我的猜想,我对 webpack 配置做了改造:
const CopyPlugin = require('copy-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
module.exports = {
mode: 'production',
plugin: [
new CopyPlugin({
patterns: [
{
from: '**/*.js' // 去掉了 transform
{
from: '**/*.css'
]
})
],
optimization: {
minimizer: [
new TerserPlugin({
terserOptions: {
module: true,
},
}),
new CssMinimizerPlugin(),
],
}
}
果然—— js 和 css 被压缩了 :joy:
总结
- Webpack v5 在 production 模式下,会将 TerserPlugin 加入进
optimization.minimizer中- 但是,如果想要修改 TerserPlugin 的默认设置,还是需要自行在
optimization.minimizer中声明 TerserPlugin
- 但是,如果想要修改 TerserPlugin 的默认设置,还是需要自行在
optimization.minimizer会对 entry 以及 entry 外(或者说所有经由 webpack emit 的文件)生效- 但奇怪的是我在 webpack 文档里找不到关于这一点的说明