webpack5 升级记录
2021-03-15 · 1,109 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
参考#
- Webpack 5 release: https://webpack.js.org/blog/2020-10-10-webpack-5-release/
- 官方升级指南: https://webpack.js.org/migrate/5/