从 v4 到 v5

本指南旨在帮助你在直接使用 webpack 时迁移到 webpack 5。如果你正在使用更高级别的工具来运行 webpack,请参考该工具的迁移说明。

准备

Webpack 5 至少需要 Node.js 10.13.0 (LTS),因此,如果你仍在运行较旧版本,请确保升级你的 Node.js。

升级 webpack 4 及其插件/加载器

  1. webpack 4 升级到最新可用版本。

    • 使用 webpack >= 4 时,升级到最新 webpack 4 版本不需要额外的指导。

    • 如果您使用的 webpack 版本低于 4,请参阅 webpack 4 迁移指南

  2. webpack-cli 升级到最新可用版本(如果使用)

  3. 将所有使用的插件和加载器升级到最新可用版本

    某些插件和加载器可能具有必须使用才能与 webpack 5 兼容的测试版。升级时务必阅读每个单独插件/加载器的发行说明,因为最新版本可能仅支持 webpack 5,并且在 v4 中会失败。在这种情况下,建议更新到支持 webpack 4 的最新版本。

确保您的构建没有错误或警告

由于 webpackwebpack-cli、插件和加载器的版本升级,可能会出现新的错误或警告。在构建过程中注意弃用警告。

您可以通过这种方式调用 webpack 以获取弃用警告的堆栈跟踪,以找出哪些插件和加载器负责。

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

由于 webpack 5 删除了所有已弃用的功能,因此请确保在构建期间没有 webpack 弃用警告才能继续。

确保使用 mode

mode 设置为 productiondevelopment 以确保设置相应的默认值。

更新过时的选项

将以下选项更新到其新版本(如果使用)

  • optimization.hashedModuleIds: trueoptimization.moduleIds: 'hashed'
  • optimization.namedChunks: trueoptimization.chunkIds: 'named'
  • optimization.namedModules: trueoptimization.moduleIds: 'named'
  • NamedModulesPluginoptimization.moduleIds: 'named'
  • NamedChunksPluginoptimization.chunkIds: 'named'
  • HashedModuleIdsPluginoptimization.moduleIds: 'hashed'
  • optimization.noEmitOnErrors: falseoptimization.emitOnErrors: true
  • optimization.occurrenceOrder: trueoptimization: { chunkIds: 'total-size', moduleIds: 'size' }
  • optimization.splitChunks.cacheGroups.vendorsoptimization.splitChunks.cacheGroups.defaultVendors
  • optimization.splitChunks.cacheGroups.test(module, chunks)optimization.splitChunks.cacheGroups.test(module, { chunkGraph, moduleGraph })
  • Compilation.entriesCompilation.entryDependencies
  • serveserve 已被弃用,建议使用 DevServer
  • Rule.query(自 v3 起已弃用)→ Rule.options/UseEntry.options
  • Rule.loadersRule.use

测试 webpack 5 兼容性

尝试在 webpack 4 配置中设置以下选项,并检查构建是否仍然正常工作。

module.exports = {
  // ...
  node: {
    Buffer: false,
    process: false,
  },
};

在为 webpack 5 升级配置时,必须再次删除这些选项。

将 webpack 升级到 5

现在,让我们将 webpack 升级到版本 5

  • npm:npm install webpack@latest

  • Yarn:yarn add webpack@latest

如果你无法在“升级 webpack 4 及其插件/加载器”步骤中将某些插件/加载器升级到最新版本,请不要忘记现在升级它们。

清理配置

  • 考虑从 webpack 配置中删除 optimization.moduleIdsoptimization.chunkIds。默认值可能会更好,因为它们支持 生产模式 中的长期缓存和 开发模式 中的调试。

  • 在 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

  • 如果你有使用 raw-loaderurl-loaderfile-loader 加载资产的已定义 rules,请改用 资产模块,因为它们将在不久的将来被弃用。

  • 如果你将 target 设置为函数,请将其更新为 false,并在 plugins 选项中应用该函数。请参阅以下示例

    // for webpack 4
    {
        target: WebExtensionTarget(nodeConfig)
    }
    
    // for webpack 5
    {
        target: false,
        plugins: [
            WebExtensionTarget(nodeConfig)
        ]
    }
  • 如果您定义了 output.library 或 output.libraryTarget,请更改属性名称:(output.libraryTarget -> output.library.type,output.library -> output.library.name)。示例

    // for webpack 4
    {
        output: {
          library: 'MyLibrary',
          libraryTarget: 'commonjs2'
        }
    }
    
    // for webpack 5
    {
        output: {
          library: {
            name: 'MyLibrary',
            type: 'commonjs2'
          }
        }
    }

如果您正在通过导入使用 WebAssembly,则应遵循以下两步流程

  • 通过设置 experiments.syncWebAssembly: true 启用已弃用的规范,以获得与 webpack 4 中相同的行为。
  • 在成功迁移到 webpack 5 后,将 experiments 值更改为 experiments: { asyncWebAssembly: true } 以使用最新的 WASM 集成规范。

重新考虑 optimization.splitChunks

  • 建议使用默认值或 optimization.splitChunks: { chunks: 'all' }
  • 在使用自定义配置时,请删除 name: false 并用 idHint: string | function 替换 name: 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':您可以省略它,这是默认值。

需要支持 IE 11 等较旧的浏览器?

  • 如果您为您的项目启用了 browserslist,webpack 5 将重复使用您的 browserslist 配置来决定为运行时代码发出哪种代码样式。

    请确保

    1. target 设置为 browserslist 或删除 target,让 webpack 自动为您设置 browserslist
    2. IE 11 添加到您的 browserslist 配置中。
  • 如果没有 browserslist,webpack 的运行时代码将使用 ES2015 语法(例如箭头函数)来构建更小的包。因此,你需要将 target: ['web', 'es5'] 设置为对浏览器(如 IE11)使用 ES5 语法,因为它们不支持 ES2015 语法。

  • 对于 Node.js,构建在 target 选项中包含受支持的 Node.js 版本,并且 webpack 将自动找出支持哪种语法,例如 target: 'node8.6'

清理代码

使用 /* webpackChunkName: '...' */

确保理解意图

  • 此处块的名称旨在公开。
  • 它不是仅限于开发的名称。
  • Webpack 将使用它在生产和开发模式中命名文件。
  • 即使不使用 webpackChunkName,Webpack 5 也将在 development 模式下自动分配有用的文件名。

从 JSON 模块中使用命名导出

新规范不支持此操作,你将收到警告。请不要

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) 形式。
    • 如果你在监视模式下使用 webpack 直到用户结束进程,则此操作是可选的。监视模式中的空闲阶段将用于此类工作。

运行单个构建并遵循建议

请务必仔细阅读构建错误/警告。如果没有相应的建议,请创建一个问题,我们会尝试解决它。

重复以下步骤,直到至少解决 3 级或 4 级

  • 1 级:架构验证失败

    配置选项已更改。应出现一个验证错误,其中包含 BREAKING CHANGE: 注释,或提示应使用哪个选项。

  • 2 级:Webpack 退出时出现错误

    错误消息应告诉你需要更改的内容。

  • 3 级:构建错误

    错误消息应包含 BREAKING CHANGE: 注释。

  • 第 4 级:生成警告

    警告消息应告知您哪些方面可以改进。

  • 第 5 级:运行时错误

    这很棘手。您可能需要调试来查找问题。此处难以提供一般性建议。但我们确实在下面列出了一些有关运行时错误的常见建议

    • process 未定义。
      • webpack 5 不再包含此 Node.js 变量的垫片。避免在前端代码中使用它。
      • 想要支持浏览器使用吗?使用 exportsimports package.json 字段,根据环境使用不同的代码。
        • 还可使用 browser 字段来支持较旧的打包器。
        • 备选方案:使用 typeof process 检查包装代码块。请注意,这会对包大小产生负面影响。
      • 想要使用 process.env.VARIABLE 中的环境变量吗?您需要使用 DefinePluginEnvironmentPlugin 在配置中定义这些变量。
        • 考虑改用 VARIABLE,并确保也检查 typeof VARIABLE !== 'undefined'process.env 属于 Node.js 特有,应避免在前端代码中使用。
    • 指向包含 auto 的 URL 的 404 错误
      • 并非所有生态系统工具都已为通过 output.publicPath: "auto" 实现的新默认自动 publicPath 做好准备
        • 改用静态 output.publicPath: ""
  • 第 6 级:弃用警告

    您可能会收到许多弃用警告。这并非直接问题。插件需要时间来赶上核心更改。请向插件报告这些弃用。这些弃用只是警告,并且生成仍将继续进行,仅有轻微缺点(如性能下降)。

    • 您可以使用 --no-deprecation 标志运行节点来隐藏弃用警告,例如:node --no-deprecation node_modules/webpack/bin/webpack.js。这应仅作为临时解决办法。
    • 插件和加载器贡献者可以遵循弃用消息中的建议来改进代码。
  • 第 7 级:性能问题

    通常,webpack 5 的性能应该会有所提高,但也有少数情况下性能会变差。

    以下是可以采取的一些措施来改善这种情况

    • 分析时间花在何处。
      • --profile --progress 现在会显示一个简单的性能分析
      • node --inspect-brk node_modules/webpack/bin/webpack.js + chrome://inspect / edge://inspect(请参见分析器选项卡)。
        • 您可以将这些分析保存到文件中,并在问题中提供它们。
        • 尝试使用 --no-turbo-inlining 标记,在某些情况下可获得更好的堆栈跟踪。
    • 通过恢复到不安全的缓存(如 webpack 4 中)可以改善增量构建中构建模块的时间
      • module.unsafeCache: true
      • 但这可能会影响处理代码库中某些更改的能力
    • 完整构建
      • 已弃用的功能的向后兼容层通常比新功能的性能更差。
      • 创建许多警告会影响构建性能,即使它们被忽略。
      • Source Maps 非常昂贵。查看文档中的 devtool 选项,了解不同选项的比较。
      • 防病毒保护可能会影响文件系统访问的性能。
      • 持久缓存有助于改善重复的完整构建。
      • 模块联合允许将应用程序拆分为多个较小的构建。

一切正常?

请发推文表示您已成功迁移到 webpack 5。 发推文

无法正常工作?

创建 问题,并告诉我们您在迁移期间遇到的问题。

本指南中缺少内容?

请打开 Pull Request,帮助使用本指南的其他人。

内部更改

对于有兴趣的人,此处列出了 webpack 内部更改,例如:添加类型、重构代码和方法重命名。但它们并非作为常见用例迁移的一部分。

  • Module.nameForConditionModule.updateCacheModuleModule.chunkCondition 不再是可选的。

加载器的 getOptions 方法

Webpack 5 内置 this.getOptions 方法,可在加载器上下文中使用。对于之前使用 schema-utils 中首选的 getOptions 方法的加载器来说,这是一个重大更改

  • this.getOptions 自 webpack 5 起可用
  • 它支持 JSON 作为查询字符串,而不是 JSON5:?{arg:true}?{"arg":true}。在各自的加载器文档中,应将使用 JSON5 视为已弃用,并记录为 JSON 的替代方案。
  • loader-utils 具有解析查询字符串的特定行为(truefalsenull 不会解析为 string,而是解析为原始值)。对于新的内置 this.getOptions 方法不再是这种情况,它使用本机 querystring 解析(随 Node.js 一起提供)。在使用 this.getOptions 方法获取选项后,仍然可以在加载器代码中为这些情况添加自定义行为。
  • 对于新的 this.getOptions 方法,架构参数是可选的,但我们强烈建议为加载器的选项添加架构验证。架构中的 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.

10 位贡献者

sokrasalemhilalkeichingerEugeneHlushkoMattGoldwaterrramaachenxsanjamesgeorge007getsnoopyyevhen-logosha