# 六.环境相关配置

前言

  • 开发环境:开发时使用,构建结果用于本地开发调试,不进行代码压缩,打印 debug 信息,包含 sourcemap 文件
  • 生产环境:构建后的结果是直接应用于线上的,即代码都是压缩后,运行时不打印 debug 信息,静态文件不包括 sourcemap 的

# 1.在配置文件中区分 mode

  • 1.配置文件可以对外暴露一个函数,接受环境变量区分不同环境
module.exports = (env, argv) => ({
  // ... 其他配置
  optimization: {
    minimize: false,
    // 使用 argv 来获取 mode 参数的值
    minimizer:
      argv.mode === "production"
        ? [
            new UglifyJsPlugin({
              /* 你自己的配置 */
            }),
            // 仅在我们要自定义压缩配置时才需要这么做
            // mode 为 production 时 webpack 会默认使用压缩 JS 的 plugin
          ]
        : [],
  },
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  • 2.NODE_ENV 方式注入环境变量

    • package.json

      {
        "scripts": {
          "build": "NODE_ENV=production webpack",
          "develop": "NODE_ENV=development webpack-dev-server"
        }
      }
      
      1
      2
      3
      4
      5
      6
    • 然后在 webpack.config.js 文件中可以通过 process.env.NODE_ENV 来获取命令传入的环境变量:

      const config = {
        // ... webpack 配置
      }
      if (process.env.NODE_ENV === "production") {
        // 生产环境需要做的事情,如使用代码压缩插件等
        config.plugins.push(new UglifyJsPlugin())
      }
      module.exports = config
      
      1
      2
      3
      4
      5
      6
      7
      8

# 2.运行时的环境变量

通过 process.env.NODE_ENV 控制是否打印 debug 信息

export default function log(...args) {
  if (process.env.NODE_ENV === "development" && console && console.log) {
    console.log.apply(console, args)
  }
}
1
2
3
4
5

# 3.常见的环境差异配置

前面提及的使用环境变量的方式可以让我们在不同的构建环境中完成不同的构建需求,这里列举一下常见的 webpack 构建差异配置:

  • 生产环境可能需要分离 CSS 成单独的文件,以便多个页面共享同一个 CSS 文件
  • 生产环境需要压缩 HTML/CSS/JS 代码
  • 生产环境需要压缩图片
  • 开发环境需要生成 sourcemap 文件
  • 开发环境需要打印 debug 信息
  • 开发环境需要 live reload 或者 hot reload 的功能

以上是常见的构建环境需求差异,可能更加复杂的项目中会有更多的构建需求(如划分静态域名等),但是我们都可以通过判断环境变量来实现这些有环境差异的构建需求。

webpack 中 mode 为 production 时默认使用 JS 代码压缩,而 mode 为 development 时默认启用 hot reload,等等。这样让我们的配置更为简洁,我们只需要针对特别使用的 loader 和 plugin 做区分配置就可以了。

# 4.拆分配置

把 webpack 的配置按照不同的环境拆分成多个文件,运行时直接根据环境变量加载对应的配置即可。基本的划分如下:

  • webpack.base.js:基础部分,即多个文件中共享的配置
  • webpack.development.js:开发环境使用的配置
  • webpack.production.js:生产环境使用的配置
  • webpack.test.js:测试环境使用的配置

首先我们要明白,对于 webpack 的配置,其实是对外暴露一个 JS 对象,所以对于这个对象,我们都可以用 JS 代码来修改它,例如:

const config = {
  // ... webpack 配置
}
// 我们可以修改这个 config 来调整配置,例如添加一个新的插件
config.plugins.push(new YourPlugin())

module.exports = config
1
2
3
4
5
6
7

webpack.base.js

module.exports = {
  entry: "...",
  output: {
    // ...
  },
  resolve: {
    // ...
  },
  module: {
    // 这里是一个简单的例子,后面介绍 API 时会用到
    rules: [
      {
        test: /\.js$/,
        use: ["babel"],
      },
    ],
    // ...
  },
  plugins: [
    // ...
  ],
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  • webpack-merge 提供的 smart 方法,可以帮助我们更加轻松地处理 loader 配置的合并

webpack.development.js

const { smart } = require("webpack-merge")
const webpack = require("webpack")
const base = require("./webpack.base.js")

module.exports = smart(base, {
  module: {
    rules: [
      // 用 smart API,当这里的匹配规则相同且 use 值都是数组时,smart 会识别后处理
      // 和上述 base 配置合并后,这里会是 { test: /\.js$/, use: ['babel', 'coffee'] }
      // 如果这里 use 的值用的是字符串或者对象的话,那么会替换掉原本的规则 use 的值
      {
        test: /\.js$/,
        use: ["coffee"],
      },
      // ...
    ],
  },
  plugins: [
    // plugins 这里的数组会和 base 中的 plugins 数组进行合并
    new webpack.DefinePlugin({
      "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV),
    }),
  ],
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24