Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

重新认识 Webpack 的 optimization.minimizer #127

Open
lmk123 opened this issue Aug 1, 2023 · 0 comments
Open

重新认识 Webpack 的 optimization.minimizer #127

lmk123 opened this issue Aug 1, 2023 · 0 comments

Comments

@lmk123
Copy link
Owner

lmk123 commented Aug 1, 2023

我有一个项目的 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 被压缩了 😂

总结

  • Webpack v5 在 production 模式下,会将 TerserPlugin 加入进 optimization.minimizer
    • 但是,如果想要修改 TerserPlugin 的默认设置,还是需要自行在 optimization.minimizer 中声明 TerserPlugin
  • optimization.minimizer 会对 entry 以及 entry 外(或者说所有经由 webpack emit 的文件)生效
    • 但奇怪的是我在 webpack 文档里找不到关于这一点的说明
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant