生产

在本指南中,我们将深入探讨构建生产网站或应用程序的一些最佳实践和实用程序。

设置

开发生产构建的目标差异很大。在开发中,我们希望有强大的源映射和带有实时重新加载或热模块替换的本地主机服务器。在生产中,我们的目标转向关注最小化捆绑包、更轻量级的源映射和优化的资产以提高加载时间。有了这种逻辑上的分离,我们通常建议为每个环境编写单独的 webpack 配置

虽然我们将分离生产开发特定的部分,但请注意,我们仍然会维护一个“通用”配置以保持 DRY。为了将这些配置合并在一起,我们将使用一个名为 webpack-merge 的实用程序。有了“通用”配置,我们就不必在环境特定的配置中重复代码。

让我们从安装 webpack-merge 并拆分我们在之前指南中已经完成的部分开始

npm install --save-dev webpack-merge

项目

  webpack-demo
  |- package.json
  |- package-lock.json
- |- webpack.config.js
+ |- webpack.common.js
+ |- webpack.dev.js
+ |- webpack.prod.js
  |- /dist
  |- /src
    |- index.js
    |- math.js
  |- /node_modules

webpack.common.js

+ const path = require('path');
+ const HtmlWebpackPlugin = require('html-webpack-plugin');
+
+ module.exports = {
+   entry: {
+     app: './src/index.js',
+   },
+   plugins: [
+     new HtmlWebpackPlugin({
+       title: 'Production',
+     }),
+   ],
+   output: {
+     filename: '[name].bundle.js',
+     path: path.resolve(__dirname, 'dist'),
+     clean: true,
+   },
+ };

webpack.dev.js

+ const { merge } = require('webpack-merge');
+ const common = require('./webpack.common.js');
+
+ module.exports = merge(common, {
+   mode: 'development',
+   devtool: 'inline-source-map',
+   devServer: {
+     static: './dist',
+   },
+ });

webpack.prod.js

+ const { merge } = require('webpack-merge');
+ const common = require('./webpack.common.js');
+
+ module.exports = merge(common, {
+   mode: 'production',
+ });

webpack.common.js 中,我们现在已经设置了 entryoutput 配置,并且我们已经包含了两个环境都需要的任何插件。在 webpack.dev.js 中,我们将 mode 设置为 development。此外,我们还添加了该环境的推荐 devtool(强大的源映射),以及我们的 devServer 配置。最后,在 webpack.prod.js 中,mode 设置为 production,它加载 TerserPlugin,它是在 tree shaking 指南中首次介绍的。

请注意在环境特定配置中使用 merge() 调用以将我们的通用配置包含在 webpack.dev.jswebpack.prod.js 中。webpack-merge 工具提供了多种用于合并的先进功能,但对于我们的用例,我们不需要任何这些功能。

NPM 脚本

现在,让我们修改 npm 脚本以使用新的配置文件。对于运行 `webpack-dev-server` 的 `start` 脚本,我们将使用 `webpack.dev.js`,而对于运行 `webpack` 以创建生产构建的 `build` 脚本,我们将使用 `webpack.prod.js`

package.json

  {
    "name": "development",
    "version": "1.0.0",
    "description": "",
    "main": "src/index.js",
    "scripts": {
-     "start": "webpack serve --open",
+     "start": "webpack serve --open --config webpack.dev.js",
-     "build": "webpack"
+     "build": "webpack --config webpack.prod.js"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "devDependencies": {
      "css-loader": "^0.28.4",
      "csv-loader": "^2.1.1",
      "express": "^4.15.3",
      "file-loader": "^0.11.2",
      "html-webpack-plugin": "^2.29.0",
      "style-loader": "^0.18.2",
      "webpack": "^4.30.0",
      "webpack-dev-middleware": "^1.12.0",
      "webpack-dev-server": "^2.9.1",
      "webpack-merge": "^4.1.0",
      "xml-loader": "^1.2.1"
    }
  }

请随意运行这些脚本,并观察随着我们继续添加生产配置,输出如何变化。

指定模式

许多库会根据 `process.env.NODE_ENV` 变量来确定应该包含哪些内容。例如,当 `process.env.NODE_ENV` 未设置为 `'production'` 时,一些库可能会添加额外的日志记录和测试以方便调试。但是,当 `process.env.NODE_ENV` 设置为 `'production'` 时,它们可能会删除或添加大量代码以优化实际用户运行方式。从 webpack v4 开始,指定 mode 会通过 DefinePlugin 自动为您配置 `process.env.NODE_ENV`

webpack.prod.js

  const { merge } = require('webpack-merge');
  const common = require('./webpack.common.js');

  module.exports = merge(common, {
    mode: 'production',
  });

如果您使用的是像 react 这样的库,您实际上应该会在添加 `DefinePlugin` 后看到捆绑包大小显着下降。此外,请注意,我们任何本地 `src` 代码也可以根据此进行判断,因此以下检查将是有效的

src/index.js

  import { cube } from './math.js';
+
+ if (process.env.NODE_ENV !== 'production') {
+   console.log('Looks like we are in development mode!');
+ }

  function component() {
    const element = document.createElement('pre');

    element.innerHTML = [
      'Hello webpack!',
      '5 cubed is equal to ' + cube(5)
    ].join('\n\n');

    return element;
  }

  document.body.appendChild(component());

缩小

Webpack v4+ 默认情况下会在 生产模式 下缩小您的代码。

请注意,虽然 TerserPlugin 是缩小的一个很好的起点,并且默认情况下使用,但还有其他选择

如果您决定尝试其他缩小插件,请确保您的新选择也像 树摇 指南中所述那样删除死代码,并将其提供为 optimization.minimizer

源映射

我们建议您在生产中启用源映射,因为它们对调试和运行基准测试很有用。也就是说,您应该选择一个构建速度相当快的,并且推荐用于生产使用的源映射(请参阅 devtool)。在本指南中,我们将使用生产中的 `source-map` 选项,而不是开发中使用的 `inline-source-map`

webpack.prod.js

  const { merge } = require('webpack-merge');
  const common = require('./webpack.common.js');

  module.exports = merge(common, {
    mode: 'production',
+   devtool: 'source-map',
  });

最小化 CSS

在生产环境中最小化 CSS 至关重要。请参阅 生产环境最小化 部分。

CLI 替代方案

上面描述的许多选项都可以作为命令行参数设置。例如,optimization.minimize 可以使用 --optimization-minimize 设置,mode 可以使用 --mode 设置。运行 npx webpack --help=verbose 以获取完整的 CLI 参数列表。

虽然这些简写方法很有用,但我们建议在 webpack 配置文件中设置这些选项,以便获得更多可配置性。

21 位贡献者

rajagopal4890markeriksonsimon04kisnowschrisVillanuevaswapnilmishrabring2dipredianskipjackxgqfrmskelsetxgirmamehrdaadSevenOutmanAnayaDesignwizardofhogwartsaholznerEugeneHlushkosnitin315