webpack5 升级记录

2021-03-15 · 1,108 chars · 6 min read

升级#

webpack 5 发布已经挺久的了,但是项目使用的部分核心库,没有配套升级。所以一直 pending 到现在。

具体过程不细说,每个项目的配置不同,可能问题也不同。我把我遇到的问题记录在了文章结尾,供大家参考。

性能对比#

构建(production)#

耗时#

新旧版本分别构建了 5 次,webpack5 表现稳定,......都更慢

  • webpack4: (46.06+44.24+42.94+43.49+42.94)/5 = 43.93 s
  • webpack5: (74.50+70.07+78.41+73.56+78.52)/5 = 75.01 s

项目原因,构建是多份配置串行执行的,所以时间是总时长。而且,第一,构建部署操作不会特别频繁;第二,整个部署流程中,时间瓶颈也不在构建上。所以这个时间只要不是变得特别长,可以暂时忽略,优先考虑本地启动时间。

文件体积#

以页面为维度,保持打包方式不变,js 体积上,使用 webpack5,parsed 降低约 5%,gzip 可以降低约 9%

本地启动#

相比于构建耗时,本地启动速度对开发效率的影响更大。由于测试项目使用 SSR+CSR 的同构架构,本地启动选择 client 端的编译耗时做对比,同样分别启动 5 次

  • webpack4: (25.04+24.14+23.65+23.49+23.02)/5 = 23.87 s
  • webpack5: (31.42+31.19+29.29+28.77+31.14)/5 = 30.36 s

项目本身已经做了不少优化,例如开启 babel-loader 的缓存。这次直接升级 webpack,loader,plugin,启动速度反而下降了。

开启 webpack 的本地缓存:

{
  cache: {
    type: 'filesystem',
    name: target // 因为有 SSR,所以要区分 name
  }
}

再次测试:

  • webpack5: (4.29+4.48+4.17+4.32+4.22)/5 = 4.3 s

效果明显

问题记录#

问题 1#

[webpack-cli] Error: Unknown option '--display-error-details'

--display-error-details 这个命令没了,可以在配置文件里设置

问题 2#

[webpack-cli] TypeError: webpack.HashedModuleIdsPlugin is not a constructor

HashedModuleIdsPlugin 可以去掉了,使用 optimization.moduleIds 代替,mode 设定为 production 和 development 时,optimization.moduleIds 都有默认值,一般不用管。

参考:https://github.com/webpack/webpack/issues/11631

问题 3#

[webpack-cli] Error: [webpack-node-externals] : Option 'whitelist' is not supported. Did you mean 'allowlist'?

webpack-node-externals 升级后参数变了,改为 allowlist

问题 4#

[webpack-cli] Error: Universal Chunk Loading is not implemented yet

查询官方文档发现,当 target 设置 ["web", "node"] 时,会出现“未实现的 universal chunk loading”。

问题出在 target 的默认值上,默认值是 browserlist。webpack 会自动分析项目里的 .browserslistrc,判断 target,而我项目里的 .browserslistrc,刚好 web,node 都有。

所以要解决这个问题,必须在配置里明确设置 target,避免 webpack 自动分析出错误的值。

问题 5#

出现很多弃用警告

跟踪详细的问题来源,有两种方案,一是:

node --trace-deprecation node_modules/webpack/bin/webpack.js

二是临时在 webpack.config.js 里开启:

process.traceDeprecation = true;

加完再次执行 build,问题很多,简单列几条

  • (node:33415) [DEP_WEBPACK_MAIN_TEMPLATE_RENDER_MANIFEST] DeprecationWarning: MainTemplate.hooks.renderManifest is deprecated (use Compilation.hooks.renderManifest instead)
  • (node:33415) [DEP_WEBPACK_MAIN_TEMPLATE_HASH_FOR_CHUNK] DeprecationWarning: MainTemplate.hooks.hashForChunk is deprecated (use JavascriptModulesPlugin.getCompilationHooks().chunkHash instead)
  • (node:33415) [DEP_WEBPACK_COMPILATION_NORMAL_MODULE_LOADER_HOOK] DeprecationWarning: Compilation.hooks.normalModuleLoader was moved to NormalModule.getCompilationHooks(compilation).loader
  • (node:33415) [DEP_WEBPACK_COMPILATION_OPTIMIZE_CHUNK_ASSETS] DeprecationWarning: optimizeChunkAssets is deprecated (use Compilation.hooks.processAssets instead and use one of Compilation.PROCESSASSETS_STAGE* as stage option)
  • (node:33415) [DEP_WEBPACK_EXTERNALS_FUNCTION_PARAMETERS] DeprecationWarning: The externals-function should be defined like ({context, request}, cb) => { ... }
  • (node:33415) [DEP_WEBPACK_COMPILATION_ASSETS] DeprecationWarning: Compilation.assets will be frozen in future, all modifications are deprecated.
  • (node:33415) [DEP_WEBPACK_MODULE_ID] DeprecationWarning: Module.id: Use new ChunkGraph API
  • (node:33415) [DEP_WEBPACK_MODULE_UPDATE_HASH] DeprecationWarning: Module.updateHash: Use new ChunkGraph API
  • (node:33415) [DEP_WEBPACK_CHUNK_MODULES_ITERABLE] DeprecationWarning: Chunk.modulesIterable: Use new ChunkGraph API
  • ......

大体思路就是定位出错位置,是 loader,plugin 的话,先尝试升级。然后查阅官方文档,用新的配置替换旧的,无效的配置就直接去掉。

在我的项目里,升级了这几个组件:

  • mini-css-extract-plugin
  • terser-webpack-plugin
  • 用 css-minimizer-webpack-plugin 替换 optimize-css-assets-webpack-plugin

配置方面的变动:

  • config.externals 函数签名变了。原来是 (context, request, callback),webpack 5 是 ({context, request}, cb)

问题 6#

devtool 的格式改了,这块参考新的文档重新设置就好

问题 7#

mini-css-extract-plugin 报了很多 conflicting order warning

warning 的具体意思,这个 issue 里面讲的很清楚了 https://github.com/webpack-contrib/mini-css-extract-plugin/issues/250。

这个问题最早是 2018 年出现,但是之前使用 webpack 4 的时候并没有遇到,webpack 5 升级时才出现,所以那个 issues 的时间跨度也很长。

我的项目里正常的构建不会有问题,只有本地开发才抛 warning,所以先直接用 ignoreOrder 忽略掉了。

问题 8#

如果通过 babel-plugin-react-css-modules 和 css-loader 来实现 css modules,在升级后,由于 css-loader 算法的更新,css 的 className 可能匹配不上,解决方案在这里:https://github.com/gajus/babel-plugin-react-css-modules/issues/291#issuecomment-747143987

参考#

赞赏

微信