本指南目标是帮助你在使用 webpack 的时候直接迁移到 webpack 5。如果你使用运行 webpack 更底层的工具,请 参考工具有关迁移的指引。
Webpack 5 对 Node.js 的版本要求至少是 10.13.0 (LTS),因此,如果你还在使用旧版本的 Node.js,请升级它们。
webpack
4 至最新的可用版本。当使用 webpack >= 4 时,升级到最新的 webpack 5 版本无需额外的操作。
如果你使用的 webpack 版本小于 4,请查阅 webpack 4 迁移指南。
升级 webpack-cli
到最新的可用版本(如已使用的情况下)
升级所有使用到的 plugin 和 loader 为最新的可用版本。
部分 plugin 和 loader 可能会有一个 beta 版本,必须使用它们才能与 webpack 5 兼容。 请确保在升级时阅读每个插件/loader 的发布说明,因为最新版本可能只支持 webpack 5,而在 v4 中会运行失败。在这种情况下,建议升级到支持 webpack 4 的最新版本。
由于升级了 webpack
,webpack-cli
,plugin 以及 loader 的版本,因此,可能会出现新的错误或警告。在编译过程中请注意是否有弃用警告。
你可以通过如下方式调用 webpack
来获取堆栈信息中的弃用警告,从而找出是哪个 plugin 或 loader 造成的。
node --trace-deprecation node_modules/webpack/bin/webpack.js
由于 webpack 5 移除了所有被废弃的特性,因此,需确保在构建过程中没有 webpack 的弃用警告才能继续。
mode
将 mode 设置成 production
或 development
以确保相应的默认值被设置。
如有使用以下的配置项,请升级至最新的版本:
optimization.hashedModuleIds: true
→ optimization.moduleIds: 'hashed'
optimization.namedChunks: true
→ optimization.chunkIds: 'named'
optimization.namedModules: true
→ optimization.moduleIds: 'named'
NamedModulesPlugin
→ optimization.moduleIds: 'named'
NamedChunksPlugin
→ optimization.chunkIds: 'named'
HashedModuleIdsPlugin
→ optimization.moduleIds: 'hashed'
optimization.noEmitOnErrors: false
→ optimization.emitOnErrors: true
optimization.occurrenceOrder: true
→ optimization: { chunkIds: 'total-size', moduleIds: 'size' }
optimization.splitChunks.cacheGroups.vendors
→ optimization.splitChunks.cacheGroups.defaultVendors
Compilation.entries
→ Compilation.entryDependencies
serve
→ serve
已被移除,推荐使用 DevServer
Rule.query
(从 v3 开始被移除) → Rule.options
/UseEntry.options
尝试在 webpack 4 的配置中添加如下选项,检查一下构建是否仍然正确的运行。
module.exports = {
// ...
node: {
Buffer: false,
process: false,
},
};
你必须在升级 webpack 5 的配置时,必须删除这些选项。
现在,让我们升级至 webpack 5:
npm: npm install webpack@latest
Yarn: yarn add webpack@latest
如果你之前在升级 webpack 4 时不能将某些插件或者 loader 升级到最新版本,现在不要忘了升级。
请考虑将 optimization.moduleIds
和 optimization.chunkIds
从你 webpack 配置中移除。使用默认值会更合适,因为它们会在 production 模式
下支持长效缓存且可以在 development
模式下进行调试。
当 webpack 配置中使用了 [hash]
占位符时,请考虑将它改为 [contenthash]
。效果一致,但事实证明会更为有效。
如果你使用了 Yarn 的 PnP 以及 pnp-webpack-plugin
插件,你可以将其从配置中移除,因为它已被默认支持。
如果你使用了带有正则表达式参数的 IgnorePlugin
,现已支持传入一个 options
对象:new IgnorePlugin({ resourceRegExp: /regExp/ })
。
如果你使用了类似于 node.fs: 'empty'
,请使用 resolve.fallback.fs: false
代替。
如果你在 webpack 的 Node.js API 中使用了 watch: true
,请移除它。无需按编译器的提示设置它,当执行 watch()
时为 true
,当执行 run()
的时候为 false
。
如果你定义了 rules
,以使用 raw-loader
,url-loader
或 file-loader
来加载资源,请使用 资源模块 替代,因为它们可能在不久的将来被淘汰。
如果你将 target
设置为函数,则应将其更新为 false
,然后在 plugins
选项中使用该函数。具体示例如下:
// for webpack 4
{
target: WebExtensionTarget(nodeConfig)
}
// for webpack 5
{
target: false,
plugins: [
WebExtensionTarget(nodeConfig)
]
}
如果通过 import 使用了 WebAssembly,应遵循以下两点:
experiments.syncWebAssembly: true
配置,以启用废弃提醒,获得在 webpack 4 中的相同行为。experiments
的值改为 experiments: { asyncWebAssembly: true }
以使用最新规范的 WASM。重新考虑 optimization.splitChunks
的配置:
optimization.splitChunks: { chunks: 'all' }
配置。name: false
,并将 name: string | function
替换为 idHint: string | function
。optimization.splitChunks.cacheGroups: { default: false, vendors: false }
配置可以关闭默认值。但我们不推荐这么做,如果你需要在 webpack 5 中获得与之相同的效果:请将配置改为 optimization.splitChunks.cacheGroups: { default: false, defaultVendors: false }
。考虑移除的默认值:
entry: './src/index.js'
时,你可以省略它,此为默认值。output.path: path.resolve(__dirname, 'dist')
时:你可以省略它,此为默认值。output.filename: '[name].js'
时:你可以省略它,此为默认值。如果你在项目中启用了 browserslist,webpack 5 将会重用你的 browserslist
配置来决定运行时的代码风格。
只要确保:
target
设置为 browserslist
,或者移除 target
配置,webpack 会自动将其置为 browserslist
。IE 11
。如未使用 browserslist
,webpack 的运行时代码将默认使用 ES2015 语法(例如,箭头函数)来构建一个简洁的 bundles。如果你构建的目标环境并不支持 ES2015 的语法(如 IE 11),你需要设置 target: ['web', 'es5']
以使用 ES5 的语法。
对于 Node.js 环境来说,构建中引入了对 Node.js 版本的支持,webpack 会自动找出对应版本支持的语法,例如,target: 'node8.6'
。
/* webpackChunkName: '...' */
时请确保你了解其意图:
webpackChunkName
,webpack 5 也会自动在 development
模式下分配有意义的文件名。新规范中将不再支持下面这种方式,如此做会发出警告:
import { version } from './package.json';
console.log(version);
请使用如下方式代替:
import pkg from './package.json';
console.log(pkg.version);
const compiler = webpack(...);
,确保在使用完毕后,使用 compiler.close(callback);
关闭编译器。webpack(..., callback)
。请务必仔细阅读构建时的错误/警告。如未发现相关建议,请创建一个 issue,我们会尽力解决。
重复以下步骤,直到你至少解决到 Level 3 或 Level 4:
Level 1: 模式(Schema)校验失败。
配置选项已更改。应该要有校验失败的信息且附上 BREAKING CHANGE:
提示,或提示应该使用哪个选项。
Level 2: webpack 异常退出并出现错误。
错误信息应告诉你哪里需要进行修改。
Level 3: 构建错误。
错误信息应该要有 BREAKING CHANGE:
提示。
Level 4: 构建警告。
警告信息应该告诉你哪里需要进行修改。
Level 5: 运行时错误。
这很棘手,你可能要调试才能找到问题所在。在这里很难给出一个通用的建议。但我们在下面列出了一些关于运行时错误的常见建议:
process
未定义。exports
或 imports
中的 package.json 字段,会根据环境不同使用不同的代码。browser
字段来支持旧的 bundlers。typeof process
检查包裹的代码块。请注意,这将对 bundle 大小产生负面影响。process.env.VARIABLE
?你需要使用 DefinePlugin
或 EnvironmentPlugin
在配置中定义这些变量。VARIABLE
代替,但需要检查 typeof VARIABLE !== 'undefined'
。process.env
是 Node.js 特有,应避免在前端中使用。auto
的 URLpublicPath
的默认值 output.publicPath: "auto"
output.publicPath: ""
代替。Level 6: 弃用警告.
你可能会收到很多弃用警告,插件需要时间来赶上内核的变化。请将这些弃用上报给插件。这些弃用只是警告,构建仍然可以正常工作,只是会有小瑕疵(比如性能降低)。
--no-deprecation
选项的 node 运行 webpack,可以隐藏废弃告警,例如:node --no-deprecation node_modules/webpack/bin/webpack.js
。但这只能作为临时的解决方案。Level 7: 性能问题.
一般来说,webpack 5 的性能应该会有所提高,但也存在少数情况性能会变差。
而在这里,你可以做一些事情来改善这种情况:
--profile --progress
可以展示一个简单的性能曲线。node --inspect-brk node_modules/webpack/bin/webpack.js
+ chrome://inspect
/ edge://inspect
(查看 profiler 选项)。--no-turbo-inlining
选项,在某些情况下可以获得更好的堆栈信息。module.unsafeCache: true
devtool
选项以比较使用不同选项的代价。如果你成功地迁移至 webpack 5。请发推 @ 我们。
创建一个 issue 并告诉我们在迁移过程中你遇到的问题。
请提交 Pull Request 以帮助其他开发者更好地使用该指南。
如果你对内核感兴趣,此处会列出 webpack 内核相关的变更,如:添加类型,代码重构和方法重命名等。但这些变化并不会作为迁移通用案例的一部份。
Module.nameForCondition
,Module.updateCacheModule
以及 Module.chunkCondition
不再可选。Webpack 5 发布后,在 loader 的上下文中,会带有内置的 this.getOptions
方法。这对于那些使用之前推荐 schema-utils 中的 getOptions
方法的 loader 而言,这是一个重大更新:
this.getOptions
自 webpack 5 起支持使用?{arg:true}
→ ?{"arg":true}
。在相应的 loader 文档中,应推荐使用 JSON 并不推荐使用 JSON5。loader-utils
拥有解析查询字符串的特定行为(如 true
,false
以及 null
不会被解析成 string
而是原始类型的值)。这对于新的内置 this.getOptions
方法来说,不再适用,它使用 Node 原生的 querystring
方法进行解析。此时,需在 loader 中使用 this.getOptions
获取配置选项之后,根据情况添加自定义行为。this.getOptions
方法而言是可选的,但我们强烈建议给你的 loader 选项添加模式校验。模式中的 title
字段,可用于自定义校验的错误信息,比如 "title": "My Loader ooooptions"
会在这种方式展示错误信息:Invalid ooooptions object. My Loader has been initialised using an ooooptions object that does not match the API schema. - ooooptions.foo.bar.baz should be a string.
。