生产环境

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

设置

开发生产构建的目标差异很大。在开发环境中,我们希望有强大的源映射和具有实时重载或热模块替换功能的 localhost 服务器。在生产环境中,我们的目标转向专注于压缩后的包、更轻量的源映射和优化的资产以提高加载时间。鉴于这种逻辑上的分离,我们通常建议为每个环境编写单独的 webpack 配置

虽然我们将分离出生产环境开发环境特定的部分,但请注意,我们仍将维护一个“通用”配置以保持 DRY(Don't Repeat Yourself)原则。为了将这些配置合并在一起,我们将使用一个名为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-serverstart脚本,我们将使用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是代码压缩的绝佳起点,并且默认使用,但还有其他选项可用

如果您决定尝试其他代码压缩插件,请确保您的新选择也能够像tree shaking指南中所述那样删除无用代码,并将其作为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