可打印

迁移

本节包含从旧版本 webpack 迁移到新版本的信息。

从 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 的最新版本。

Codemods

为了协助从 webpack v4 升级到 v5,Codemod 提供了开源社区代码修改器,可以帮助自动化大部分迁移过程。

请注意,这些不是官方的 webpack 代码修改器,虽然它旨在简化迁移,但可能无法涵盖所有情况。您可能仍然需要执行额外的手动步骤才能完全完成升级。

运行 webpack v5 迁移代码修改器

npx codemod@latest webpack/v5/migration-recipe

这将运行 Codemod 注册表中的以下代码修改器:

每个代码修改器都自动化了 webpack v5 迁移指南中列出的一个更改。有关可用的 webpack v5 代码修改器的完整列表,请参阅 Codemod 注册表

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

由于 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()truerun()false

  • 如果您定义了用于使用 raw-loaderurl-loaderfile-loader 加载资源的 rules,请改用 Asset Modules,因为它们将在不久的将来被弃用。

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

    // for webpack 4
    {
        target: WebExtensionTarget(nodeConfig)
    }
    
    // for webpack 5
    {
        target: false,
        plugins: [
            WebExtensionTarget(nodeConfig)
        ]
    }

    注意:此更改的代码修改器

    npx codemod webpack/v5/set-target-to-false-and-update-plugins

    (请参阅此处注册表。)

  • 如果您定义了 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'
          }
        }
    }

    注意:此更改的代码修改器

    npx codemod webpack/v5/migrate-library-target-to-library-object

    (请参阅此处注册表。)

如果您通过 import 使用 WebAssembly,您应该遵循以下两步流程

  • 通过设置 experiments.syncWebAssembly: true 来启用已弃用的规范,以获得与 webpack 4 中相同的行为。
  • 成功迁移到 webpack 5 后,将 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':您可以省略它,这是默认值。

需要支持像 IE 11 这样的旧浏览器吗?

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

    确保

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

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

清理代码

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

确保理解意图

  • 这里的 chunk 名称旨在公开。
  • 它不是一个仅用于开发环境的名称。
  • Webpack 将在生产和开发模式下使用它来命名文件。
  • 即使不使用 webpackChunkName,Webpack 5 也会在 development 模式下自动分配有用的文件名。

使用 JSON 模块的命名导出

新规范不支持此功能,您将收到警告。与其

import { version } from './package.json';
console.log(version);

不如使用

import pkg from './package.json';
console.log(pkg.version);

注意:此更改的代码修改器

npx codemod webpack/v5/json-imports-to-default-imports

(请参阅此处注册表。)

清理构建代码

  • 当使用 const compiler = webpack(...); 时,请确保在使用后关闭编译器:compiler.close(callback);
    • 这不适用于会自动关闭的 webpack(..., callback) 形式。
    • 如果您在观察模式下使用 webpack 直到用户结束进程,这是可选的。观察模式下的空闲阶段将用于此类工作。

运行一次构建并遵循建议

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

重复以下步骤,直到您至少解决了级别 3 或 4 的问题

  • 级别 1:Schema 验证失败

    配置选项已更改。应该会有一个带有 BREAKING CHANGE: 注释的验证错误,或者一个提示应使用哪个选项的提示。

  • 级别 2:Webpack 因错误退出

    错误消息应该告诉您需要更改什么。

  • 级别 3:构建错误

    错误消息应该有一个 BREAKING CHANGE: 注释。

  • 级别 4:构建警告

    警告消息应该告诉您哪些可以改进。

  • 级别 5:运行时错误

    这很棘手。您可能需要调试才能找到问题。这里很难给出一般性建议。但我们确实在下面列出了一些关于运行时错误的常见建议

    • process 未定义。
      • webpack 5 不再包含此 Node.js 变量的 polyfill。避免在前端代码中使用它。
      • 想要支持浏览器使用?使用 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: ""
    • 无法读取未定义属性(读取 'call')
      • 如果您在运行时看到此错误,可能与 ModuleConcatenationPlugin 有关。检查您是否正在使用该插件,以及是否将其包含在配置的 plugins 部分中,并且该配置也设置为 production 模式,请从您的插件列表中移除该插件(即 new webpack.optimize.ModuleConcatenationPlugin())。在 webpack 5 中,该插件在生产模式下默认启用,并且可能会被重复包含。
      • 通常,禁用每个插件并测试构建是判断问题可能来源的好方法。
      • 有关更多详细信息,请参阅:此 issue
  • 级别 6:弃用警告

    您可能会收到大量弃用警告。这并非直接问题。插件需要时间来跟上核心更改。请向插件报告这些弃用。这些弃用仅是警告,构建仍将正常工作,只是会有一些小缺点(例如性能下降)。

    • 您可以通过运行带 --no-deprecation 标志的 node 来隐藏弃用警告,例如: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 (请参阅分析器选项卡)。
        • 您可以将这些概要保存到文件中并在 issues 中提供。
        • 在某些情况下,尝试使用 --no-turbo-inlining 标志以获得更好的堆栈跟踪。
    • 增量构建中构建模块的时间可以通过恢复到像 webpack 4 中那样的不安全缓存来改善
      • module.unsafeCache: true
      • 但这可能会影响处理代码库中某些更改的能力
    • 完整构建
      • 已弃用功能的向后兼容层通常会比新功能具有更差的性能。
      • 产生大量警告会影响构建性能,即使它们被忽略。
      • Source Map 很昂贵。查阅文档中的 devtool 选项以查看不同选项的比较。
      • 防病毒保护可能会影响文件系统访问的性能。
      • 持久化缓存有助于改善重复的完整构建。
      • 模块联邦允许将应用程序拆分为多个更小的构建。

一切正常?

请发推文告知您已成功迁移到 webpack 5。 发推文

它不工作?

创建一个 issue 并告诉我们您在迁移过程中遇到的问题。

本指南缺少内容吗?

请提交一个 拉取请求 以帮助使用本指南的下一个人。

内部更改

此处列出了 webpack 内部的更改,例如:添加类型、重构代码和方法重命名,供感兴趣的人士参考。但它们并非通用用例迁移的一部分。

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

加载器的 getOptions 方法

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

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

从 v3 迁移到 v4

本指南仅显示影响最终用户的主要更改。有关更多详细信息,请参阅更新日志

Node.js v4

如果您仍在使用 Node.js v4 或更低版本,则需要将 Node.js 安装升级到 Node.js v6 或更高版本。

有关升级您的 Node.js 版本的说明,请参阅此处

CLI

CLI 已移至一个单独的包:webpack-cli。在使用 webpack 之前,您需要安装它,请参阅基本设置

安装指南可在此处找到。

更新插件

许多第三方插件需要更新到最新版本才能与 webpack 4 兼容。流行插件的链接可在此处找到。

mode

将新的 mode 选项添加到您的配置中。根据您的配置类型将其设置为 'production''development''none'

webpack.config.js

module.exports = {
  // ...
+  mode: 'production',
}

已弃用/已移除的插件

这些插件可以从配置中移除,因为它们在生产模式下是默认的

webpack.config.js

module.exports = {
  // ...
  plugins: [
-    new NoEmitOnErrorsPlugin(),
-    new ModuleConcatenationPlugin(),
-    new DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") })
-    new UglifyJsPlugin()
  ],
}

这些插件在开发模式下是默认的

webpack.config.js

module.exports = {
  // ...
  plugins: [
-    new NamedModulesPlugin()
  ],
}

这些插件已弃用并现已移除

webpack.config.js

module.exports = {
  // ...
  plugins: [
-    new NoErrorsPlugin(),
-    new NewWatchingPlugin()
  ],
}

CommonsChunkPlugin

CommonsChunkPlugin 已移除。相反,可以使用 optimization.splitChunks 选项。

有关更多详细信息,请参阅 optimization.splitChunks 的文档。默认配置可能已经适合您的需求。

import() 和 CommonJS

在 webpack 4 中,使用 import() 加载非 ESM 时的结果已更改。现在您需要访问 default 属性来获取 module.exports 的值。

non-esm.js

module.exports = {
  sayHello: () => {
    console.log('hello world');
  },
};

example.js

function sayHello() {
  import('./non-esm.js').then((module) => {
    module.default.sayHello();
  });
}

json 和加载器

当使用自定义加载器转换 .json 文件时,您现在需要更改模块的 type

webpack.config.js

module.exports = {
  // ...
  rules: [
    {
      test: /config\.json$/,
      loader: 'special-loader',
+     type: 'javascript/auto',
      options: {...}
    }
  ]
};

如果仍在使用 json-loader,可以将其移除

webpack.config.js

module.exports = {
  // ...
  rules: [
    {
-     test: /\.json$/,
-     loader: 'json-loader'
    }
  ]
};

module.loaders

module.loaders 自 webpack 2 起已弃用,现已移除,取而代之的是 module.rules

从 v1 迁移到 v2 或 v3

以下章节描述了 webpack 1 到 2 的主要变化。

resolve.root, resolve.fallback, resolve.modulesDirectories

这些选项已被单个选项 resolve.modules 取代。有关更多用法,请参阅解析

  resolve: {
-   root: path.join(__dirname, "src")
+   modules: [
+     path.join(__dirname, "src"),
+     "node_modules"
+   ]
  }

resolve.extensions

此选项不再需要传入空字符串。此行为已移至 resolve.enforceExtension。有关更多用法,请参阅解析

resolve.*

这里有几个 API 发生了变化。由于不常用,此处未详细列出。有关详细信息,请参阅解析

module.loaders 现在是 module.rules

旧的加载器配置已被更强大的规则系统取代,该系统允许配置加载器等。出于兼容性原因,旧的 module.loaders 语法仍然有效,并且旧的名称也会被解析。新的命名约定更容易理解,并且是升级配置以使用 module.rules 的一个好理由。

  module: {
-   loaders: [
+   rules: [
      {
        test: /\.css$/,
-       loaders: [
-         "style-loader",
-         "css-loader?modules=true"
+       use: [
+         {
+           loader: "style-loader"
+         },
+         {
+           loader: "css-loader",
+           options: {
+             modules: true
+           }
+         }
        ]
      },
      {
        test: /\.jsx$/,
        loader: "babel-loader", // Do not use "use" here
        options: {
          // ...
        }
      }
    ]
  }

链式加载器

与 webpack 1 中一样,加载器可以链式传递结果。使用 rule.use 配置选项,use 可以设置为加载器数组。在 webpack 1 中,加载器通常使用 ! 进行链式操作。这种风格仅在使用旧版选项 module.loaders 时受支持。

  module: {
-   loaders: [{
+   rules: [{
      test: /\.less$/,
-     loader: "style-loader!css-loader!less-loader"
+     use: [
+       "style-loader",
+       "css-loader",
+       "less-loader"
+     ]
    }]
  }

自动移除 -loader 模块名扩展名

引用加载器时不再可能省略 -loader 扩展名

  module: {
    rules: [
      {
        use: [
-         "style",
+         "style-loader",
-         "css",
+         "css-loader",
-         "less",
+         "less-loader",
        ]
      }
    ]
  }

您仍然可以通过 resolveLoader.moduleExtensions 配置选项选择旧行为,但这不是推荐的做法。

+ resolveLoader: {
+   moduleExtensions: ["-loader"]
+ }

有关此更改的原因,请参阅#2986

不再需要 json-loader

当没有为 JSON 文件配置加载器时,webpack 将自动尝试使用 json-loader 加载 JSON 文件。

  module: {
    rules: [
-     {
-       test: /\.json/,
-       loader: "json-loader"
-     }
    ]
  }

我们决定这样做是为了消除 webpack、node.js 和 browserify 之间的环境差异。

配置中的加载器相对于 context 解析

webpack 1 中,配置的加载器是相对于匹配的文件解析的。然而,在 webpack 2 中,配置的加载器是相对于 context 选项解析的。

这解决了在使用 npm link 或引用 context 之外的模块时,加载器导致的重复模块问题。

您可以移除一些用于解决此问题的技巧

  module: {
    rules: [
      {
        // ...
-       loader: require.resolve("my-loader")
+       loader: "my-loader"
      }
    ]
  },
  resolveLoader: {
-   root: path.resolve(__dirname, "node_modules")
  }

module.preLoaders 和 module.postLoaders 已移除:

  module: {
-   preLoaders: [
+   rules: [
      {
        test: /\.js$/,
+       enforce: "pre",
        loader: "eslint-loader"
      }
    ]
  }

UglifyJsPlugin sourceMap

UglifyJsPluginsourceMap 选项现在默认为 false,而不是 true。这意味着如果您正在对最小化代码使用 source maps 或希望 uglifyjs 警告显示正确的行号,则需要将 UglifyJsPluginsourceMap 设置为 true

  devtool: "source-map",
  plugins: [
    new UglifyJsPlugin({
+     sourceMap: true
    })
  ]

UglifyJsPlugin warnings

UglifyJsPlugincompress.warnings 选项现在默认为 false,而不是 true。这意味着如果您想查看 uglifyjs 警告,需要将 compress.warnings 设置为 true

  devtool: "source-map",
  plugins: [
    new UglifyJsPlugin({
+     compress: {
+       warnings: true
+     }
    })
  ]

UglifyJsPlugin 最小化加载器

UglifyJsPlugin 不再将加载器切换到最小化模式。长期来看,minimize: true 设置需要通过加载器选项传递。请参阅加载器文档以获取相关选项。

加载器的最小化模式将在 webpack 3 或更高版本中移除。

为了保持与旧加载器的兼容性,加载器可以通过插件切换到最小化模式

  plugins: [
+   new webpack.LoaderOptionsPlugin({
+     minimize: true
+   })
  ]

DedupePlugin 已移除

不再需要 webpack.optimize.DedupePlugin。请将其从您的配置中移除。

BannerPlugin - 重大变更

BannerPlugin 不再接受两个参数,而是一个单独的选项对象。

  plugins: [
-    new webpack.BannerPlugin('Banner', {raw: true, entryOnly: true});
+    new webpack.BannerPlugin({banner: 'Banner', raw: true, entryOnly: true});
  ]

OccurrenceOrderPlugin 现在默认开启

OccurrenceOrderPlugin 现在默认启用并已重命名(在 webpack 1 中为 OccurenceOrderPlugin)。因此请务必从您的配置中移除该插件

  plugins: [
    // webpack 1
-   new webpack.optimize.OccurenceOrderPlugin()
    // webpack 2
-   new webpack.optimize.OccurrenceOrderPlugin()
  ]

ExtractTextWebpackPlugin - 重大变更

ExtractTextPlugin 需要版本 2 才能与 webpack 2 配合使用。

npm install --save-dev extract-text-webpack-plugin

此插件的配置更改主要是语法上的。

ExtractTextPlugin.extract

module: {
  rules: [
    {
      test: /.css$/,
-      loader: ExtractTextPlugin.extract("style-loader", "css-loader", { publicPath: "/dist" })
+      use: ExtractTextPlugin.extract({
+        fallback: "style-loader",
+        use: "css-loader",
+        publicPath: "/dist"
+      })
    }
  ]
}

new ExtractTextPlugin({options})

plugins: [
-  new ExtractTextPlugin("bundle.css", { allChunks: true, disable: false })
+  new ExtractTextPlugin({
+    filename: "bundle.css",
+    disable: false,
+    allChunks: true
+  })
]

完整动态 require 现在默认失败

仅带表达式(即 require(expr))的依赖现在将创建一个空上下文,而不是完整目录的上下文。

像这样的代码应该重构,因为它不适用于 ES2015 模块。如果无法重构,您可以使用 ContextReplacementPlugin 来提示编译器进行正确的解析。

在 CLI 和配置中使用自定义参数

如果您滥用 CLI 将自定义参数传递给配置,如下所示

webpack --custom-stuff

// webpack.config.js
var customStuff = process.argv.indexOf('--custom-stuff') >= 0;
/* ... */
module.exports = config;

您可能会注意到这不再被允许。CLI 现在更加严格。

取而代之的是一个用于向配置传递参数的接口。应改用此接口。未来的工具可能会依赖此接口。

webpack --env.customStuff

module.exports = function (env) {
  var customStuff = env.customStuff;
  /* ... */
  return config;
};

请参阅 CLI

require.ensure 和 AMD require 是异步的

这些函数现在总是异步的,而不是在 chunk 已经加载时同步调用其回调。

require.ensure 现在依赖于原生的 Promise。如果在缺乏 Promise 的环境中使用 require.ensure,则需要一个 polyfill。

加载器配置通过 options 实现

不再能在 webpack.config.js 中使用自定义属性配置加载器。必须通过 options 完成。以下带有 ts 属性的配置在 webpack 2 中不再有效

module.exports = {
  //...
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        loader: 'ts-loader',
      },
    ],
  },
  // does not work with webpack 2
  ts: { transpileOnly: false },
};

什么是 options

问得好。严格来说,它有两种可能;都是配置 webpack 加载器的方式。传统上,options 被称为 query,是一个可以附加到加载器名称的字符串。很像查询字符串,但实际上具有更强大的功能

module.exports = {
  //...
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        loader: 'ts-loader?' + JSON.stringify({ transpileOnly: false }),
      },
    ],
  },
};

但它也可以是与加载器一起提供的单独指定对象

module.exports = {
  //...
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        loader: 'ts-loader',
        options: { transpileOnly: false },
      },
    ],
  },
};

LoaderOptionsPlugin context

一些加载器需要上下文信息并从配置中读取。长期来看,这需要通过加载器选项传递。请参阅加载器文档以获取相关选项。

为了保持与旧加载器的兼容性,此信息可以通过插件传递

  plugins: [
+   new webpack.LoaderOptionsPlugin({
+     options: {
+       context: __dirname
+     }
+   })
  ]

debug

在 webpack 1 中,debug 选项将加载器切换到调试模式。长期来看,这需要通过加载器选项传递。请参阅加载器文档以获取相关选项。

加载器的调试模式将在 webpack 3 或更高版本中移除。

为了保持与旧加载器的兼容性,加载器可以通过插件切换到调试模式

- debug: true,
  plugins: [
+   new webpack.LoaderOptionsPlugin({
+     debug: true
+   })
  ]

使用 ES2015 进行代码分割

在 webpack 1 中,您可以使用 require.ensure() 作为方法来延迟加载应用程序的 chunk

require.ensure([], function (require) {
  var foo = require('./module');
});

ES2015 加载器规范定义 import() 作为在运行时动态加载 ES2015 模块的方法。Webpack 将 import() 视为一个分割点,并将请求的模块放入一个单独的 chunk 中。import() 接受模块名称作为参数并返回一个 Promise。

function onClick() {
  import('./module')
    .then((module) => {
      return module.default;
    })
    .catch((err) => {
      console.log('Chunk loading failed');
    });
}

好消息:现在可以处理 chunk 加载失败的情况,因为它们是基于 Promise 的。

动态表达式

可以将部分表达式传递给 import()。这与 CommonJS 中的表达式处理方式类似(webpack 会创建一个包含所有可能文件的上下文)。

import() 为每个可能的模块创建一个单独的 chunk。

function route(path, query) {
  return import(`./routes/${path}/route`).then(
    (route) => new route.Route(query)
  );
}
// This creates a separate chunk for each possible route

将 ES2015 与 AMD 和 CommonJS 混合使用

对于 AMD 和 CommonJS,您可以自由混合所有三种模块类型(甚至在同一个文件中)。在这种情况下,Webpack 的行为类似于 babel 和 node-eps

// CommonJS consuming ES2015 Module
var book = require('./book');

book.currentPage;
book.readPage();
book.default === 'This is a book';
// ES2015 Module consuming CommonJS
import fs from 'fs'; // module.exports map to default
import { readFileSync } from 'fs'; // named exports are read from returned object+

typeof fs.readFileSync === 'function';
typeof readFileSync === 'function';

重要的是,您需要告诉 Babel 不要解析这些模块符号,以便 webpack 可以使用它们。您可以通过在 .babelrcbabel-loader 选项中进行以下设置来实现这一点。

.babelrc

{
  "presets": [["es2015", { "modules": false }]]
}

提示

无需更改,但有优化机会

模板字符串

Webpack 现在支持表达式中的模板字符串。这意味着您可以开始在 webpack 结构中使用它们

- require("./templates/" + name);
+ require(`./templates/${name}`);

配置 Promise

Webpack 现在支持从配置文件返回 Promise。这允许在配置文件中进行异步处理。

webpack.config.js

module.exports = function () {
  return fetchLangs().then((lang) => ({
    entry: '...',
    // ...
    plugins: [new DefinePlugin({ LANGUAGE: lang })],
  }));
};

高级加载器匹配

Webpack 现在支持加载器更多匹配项。

module.exports = {
  //...
  module: {
    rules: [
      {
        resource: /filename/, // matches "/path/filename.js"
        resourceQuery: /^\?querystring$/, // matches "?querystring"
        issuer: /filename/, // matches "/path/something.js" if requested from "/path/filename.js"
      },
    ],
  },
};

更多 CLI 选项

有一些新的 CLI 选项供您使用

--define process.env.NODE_ENV="production" 参见 DefinePlugin

--display-depth 显示每个模块到入口点的距离。

--display-used-exports 显示模块中使用的导出信息。

--display-max-modules 设置输出中显示的模块数量(默认为 15)。

-p 现在也将 process.env.NODE_ENV 定义为 "production"

加载器更改

仅与加载器作者相关的更改。

可缓存

加载器现在默认可缓存。如果加载器不可缓存,则必须选择退出。

  // Cacheable loader
  module.exports = function(source) {
-   this.cacheable();
    return source;
  }
  // Not cacheable loader
  module.exports = function(source) {
+   this.cacheable(false);
    return source;
  }

复杂选项

webpack 1 只支持可进行 JSON.stringify 处理的加载器选项。

webpack 2 现在支持任何 JS 对象作为加载器选项。

在 webpack 2.2.1 之前(即从 2.0.0 到 2.2.0),使用复杂选项需要为 options 对象使用 ident 以允许其他加载器引用它。这在 2.2.1 中已移除,因此当前的迁移不再需要使用 ident 键。

{
  test: /\.ext/
  use: {
    loader: '...',
    options: {
-     ident: 'id',
      fn: () => require('./foo.js')
    }
  }
}

1 贡献者

webpack