webpack 设置环境变量

771 阅读3分钟

一 前言

本文内容参考自 juejin.cn/post/684490… ,部分内容经过测试有修改。

测试系统:本文中的相关代码测试环境为macOS(2021-08-06)

日常的前端开发工作中,一般会配置两套构建环境,开发环境和生产环境。

webpack提供 mode 配置选项,告知 webpack 使用相应模式的内置优化。如果没有设置,webpack 会给 mode 的默认值设置为 production

选项描述
development会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development. 为模块和 chunk 启用有效的名。
production会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production。为模块和 chunk 启用确定性的混淆名称,FlagDependencyUsagePluginFlagIncludedChunksPluginModuleConcatenationPluginNoEmitOnErrorsPlugin 和 TerserPlugin 。
none不使用任何默认优化选项

二 配置环境变量的多种方式

1. 使用命令行

写法一
  • webpack 4
"scripts": {
    "dev": "webpack-dev-server",
    "build": "webpack"
  },
  • webpack 5
"scripts": {
    "dev": "webpack server",
    "build": "webpack"
  },
  • 以上 script 脚本,可以在任意模块内通过 process.env.NODE_ENV 获取当前的环境变量
  • 但无法在 node 环境(webpack 配置文件中)下获取当前的环境变量

webpconk.config.js

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

console.log(`webpack 打印 process.env.NODE_ENV: ${process.env.NODE_ENV}\n`);
// webpack 打印 process.env.NODE_ENV: undefined

module.exports = {
  entry: {
    index: "./src/index.js",
  },
  output: {
    path: path.resolve(__dirname, "./build"),
    filename: "[name].js",
  },
  ...
};

src/index.js

console.log(`index 打印 process.env.NODE_ENV: ${process.env.NODE_ENV}\n`)
// yarn dev
// webpack4 index 打印 process.env.NODE_ENV: development
// webpack5 index 打印 process.env.NODE_ENV: production

// yarn build
// webpack4 index 打印 process.env.NODE_ENV: production
// webpack5 index 打印 process.env.NODE_ENV: production
写法二
  • webpack4
"scripts": {
    "dev2": "webpack-dev-server --mode=development",
    "build2": "webpack --mode=production"
  },
  • webpack5
"scripts": {
    "dev2": "webpack server --mode=development",
    "build2": "webpack --mode=production"
  },
  • 以上 script 脚本,可以在任意模块内通过 process.env.NODE_ENV 获取当前的环境变量, 跟随命令行--mode选项的值
  • 但无法在 node 环境(webpack 配置文件中)下获取当前的环境变量
写法三

webpack4

"scripts": {
    "dev3": "webpack-dev-server --env=development",
    "build3": "webpack --env=production"
  },

webpack5

"scripts": {
    "dev3": "webpack server --env=development",
    "build3": "webpack --env=production"
  },
  • 以上 script 脚本,在任意模块内通过 process.env.NODE_ENV 获取当前的环境变量,在开发模式下(web server),--env不管是设置development或者production,webpack4始终返回developmentwebpack5始终返回production
  • 可以在 node 环境(webpack 配置文件中)下,通过函数获取当前环境变量

webpack.config.js

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

module.exports = (env) => {
  console.log(`webpack 打印 env: `, env);
  // yarn dev3 --env=development
  // webpack4 webpack 打印 env:  development
  // webpack5 webpack 打印 env:  { WEBPACK_SERVE: true, development: true }
  
  // yarn dev3 --env=production
  // webpack4 webpack 打印 env:  production
  // webpack5 webpack 打印 env:  { WEBPACK_SERVE: true, production: true }
  
  // yarn build3 --env=development
  // webpack4 webpack 打印 env:  development
  // webpack5 webpack 打印 env:  { WEBPACK_BUNDLE: true, WEBPACK_BUILD: true, development: true }
  
  // yarn build3 --env=production
  // webpack4 webpack 打印 env:  production
  // webpack5 webpack 打印 env:  { WEBPACK_BUNDLE: true, WEBPACK_BUILD: true, production: true }
  
  return {
    entry: {
      index: "./src/index.js",
    },
    output: {
      path: path.resolve(__dirname, "./build"),
      filename: "[name].js",
    },
    ...
  };
};

src/index.js

console.log(`index 打印 process.env.NODE_ENV: ${process.env.NODE_ENV}\n`)
// yarn dev3 --env=development
// webpack4 index 打印 process.env.NODE_ENV: development
// webpack5 index 打印 process.env.NODE_ENV: production

// yarn dev3 --env=production
// webpack4 index 打印 process.env.NODE_ENV: development
// webpack5 index 打印 process.env.NODE_ENV: production

// yarn build3 --env=development or --env=production
// webpack4 index 打印 process.env.NODE_ENV: production
// webpack5 index 打印 process.env.NODE_ENV: production

2. 使用 webpack mode 配置选项

  • 和使用命令的写法二(--mode),是一样的结果
  • 可以在任意模块内通过 process.env.NODE_ENV 获取当前的环境变量,跟随mode配置选项
  • 但无法在 node 环境(webpack 配置文件中)下获取当前的环境变量

webpack.config.js

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

console.log(`webpack 打印 process.env.NODE_ENV: ${process.env.NODE_ENV}\n`);
// webpack 打印 process.env.NODE_ENV: undefined

module.exports = {
  mode: "development",
  entry: {
    index: "./src/index.js",
  },
  output: {
    path: path.resolve(__dirname, "./build"),
    filename: "[name].js",
  },
  ...
};

src/index.js

console.log(`index 打印 process.env.NODE_ENV: ${process.env.NODE_ENV}\n`)
// mode: "development"
// index 打印 process.env.NODE_ENV: development

// mode: "production"
// index 打印 process.env.NODE_ENV: production

3. 使用 webpack.DefinePlugin

DefinePlugin 允许在 编译时 将你代码中的变量替换为其他值或表达式。

  • 可以在任意模块内通过 process.env.NODE_ENV 获取当前的环境变量
  • 但无法在 node 环境(webpack 配置文件中)下获取当前的环境变量

webpack.config.js

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const webpack = require("webpack");

console.log(`webpack 打印 process.env.NODE_ENV: ${process.env.NODE_ENV}\n`); 
// webpack 打印 process.env.NODE_ENV: undefined

console.log(`webpack 打印 V_VERSION: ${V_VERSION}`);
// ReferenceError: V_VERSION is not defined

module.exports = {
  entry: {
    index: "./src/index.js",
  },
  output: {
    path: path.resolve(__dirname, "./build"),
    filename: "[name].js",
  },
  devServer: {
    contentBase: path.join(__dirname, "dist"),
    compress: false,
    port: 8000,
  },
  // 插件
  plugins: [
    new webpack.DefinePlugin({
      "process.env.NODE_ENV": JSON.stringify("development"),
      V_VERSION: JSON.stringify("v1.0.0"),
    }),
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      // 模板匹配
      template: "./src/index.html",
      filename: "index.html",
      chunks: ["index"],
    }),
  ],
};

src/index.js

console.log(`index 打印 process.env.NODE_ENV: ${process.env.NODE_ENV}\n`)
// index 打印 process.env.NODE_ENV: development

console.log(`index 打印 V_VERSION: ${V_VERSION}`)
// index 打印 V_VERSION: v1.0.0

4. 使用 cross-env 插件

写法一

webpack4

"scripts": {
    "dev4": "cross-env NODE_ENV=development V_VERSION=v2.0.0 webpack-dev-server",
    "build4": "cross-env NODE_ENV=production V_VERSION=v2.0.0 webpack"
  },

webpack5

"scripts": {
    "dev4": "cross-env NODE_ENV=development V_VERSION='v2.0.0' webpack server",
    "build4": "cross-env NODE_ENV=production V_VERSION=v2.0.0 webpack"
  },
  • 可以在任意模块内通过 process.env.NODE_ENV 获取当前的环境变量,命令行NODE_ENV的值无论是development还是production,webpack4在开发模式下(web server),值都为development,生产构建时值为productionwebpack5环境变量的值跟随命令行NODE_ENV的值
  • 可以在 node 环境(webpack 配置文件中)下获取当前的环境变量,跟随命令行NODE_ENV的值

webpack.config.js

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

console.log(`webpack 打印 process.env.NODE_ENV: ${process.env.NODE_ENV}\n`);
// yarn dev4  NODE_ENV=development
// webpack 打印 process.env.NODE_ENV: development

// yarn dev4 NODE_ENV=production
// webpack 打印 process.env.NODE_ENV: production

// yarn build4 NODE_ENV=development
// webpack 打印 process.env.NODE_ENV: development

// yarn build4 NODE_ENV=production
// webpack 打印 process.env.NODE_ENV: production

console.log(`webpack 打印 V_VERSION: ${V_VERSION}`);
// ReferenceError: V_VERSION is not defined

module.exports = {
  entry: {
    index: "./src/index.js",
  },
  output: {
    path: path.resolve(__dirname, "./build"),
    filename: "[name].js",
  },
  devServer: {
    contentBase: path.join(__dirname, "dist"),
    compress: false,
    port: 8000,
  },
  ...
};

src/index.js

console.log(`index 打印 process.env.NODE_ENV: ${process.env.NODE_ENV}\n`)
// yarn dev4 NODE_ENV=development
// webpack4 index 打印 process.env.NODE_ENV: development
// webpack5 index 打印 process.env.NODE_ENV: development

// yarn dev4 NODE_ENV=production
// webpack4 index 打印 process.env.NODE_ENV: development
// webpack5 index 打印 process.env.NODE_ENV: production

// yarn build4 NODE_ENV=development
// webpack4 index 打印 process.env.NODE_ENV: production
// webpack5 index 打印 process.env.NODE_ENV: development

// yarn build4 NODE_ENV=production
// webpack4 index 打印 process.env.NODE_ENV: production
// webpack5 index 打印 process.env.NODE_ENV: production


console.log(`index 打印 V_VERSION: ${V_VERSION}`)
// Uncaught ReferenceError: V_VERSION is not defined
写法二

webpack4

"scripts": {
    "dev5": "cross-env NODE_ENV=development webpack-dev-server --mode development",
    "build5": "cross-env NODE_ENV=production webpack --mode production"
  },

webpack5

"scripts": {
    "dev5": "cross-env NODE_ENV=development webpack server --mode development",
    "build5": "cross-env NODE_ENV=production webpack --mode production"
  },
  • 可以在任意模块内通过 process.env.NODE_ENV 获取当前的环境变量,跟随命令行--mode选项的值
  • 可以在 node 环境(webpack 配置文件中)下获取当前的环境变量,跟随命令行NODE_ENV的值

webpack.config.js

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

console.log(`webpack 打印 process.env.NODE_ENV: ${process.env.NODE_ENV}\n`);
// yarn dev5 NODE_ENV=development --mode development
// webpack 打印 process.env.NODE_ENV: development

// yarn dev5 NODE_ENV=production --mode production
// webpack 打印 process.env.NODE_ENV: production

// yarn dev5 NODE_ENV=development --mode production
// webpack 打印 process.env.NODE_ENV: development

// yarn dev5 NODE_ENV=production --mode development
// webpack 打印 process.env.NODE_ENV: production

// yarn build5 NODE_ENV=development --mode development
// webpack 打印 process.env.NODE_ENV: development

// yarn build5 NODE_ENV=production --mode production
// webpack 打印 process.env.NODE_ENV: production

// yarn build5 NODE_ENV=development --mode production
// webpack 打印 process.env.NODE_ENV: development

// yarn build5 NODE_ENV=production --mode development
// webpack 打印 process.env.NODE_ENV: production


module.exports = {
  entry: {
    index: "./src/index.js",
  },
  output: {
    path: path.resolve(__dirname, "build"),
    filename: "[name].js",
  },
  ...
};

src/index.js

console.log(`index 打印 process.env.NODE_ENV: ${process.env.NODE_ENV}\n`)
// yarn dev5 NODE_ENV=development --mode development
// index 打印 process.env.NODE_ENV: development

// yarn dev5 NODE_ENV=production --mode production
// index 打印 process.env.NODE_ENV: production

// yarn dev5 NODE_ENV=development --mode production
// index 打印 process.env.NODE_ENV: production

// yarn dev5 NODE_ENV=production --mode development
// index 打印 process.env.NODE_ENV: development

// yarn build5 NODE_ENV=development --mode development
// index 打印 process.env.NODE_ENV: development

// yarn build5 NODE_ENV=production --mode production
// index 打印 process.env.NODE_ENV: production

// yarn build5 NODE_ENV=development --mode production
// index 打印 process.env.NODE_ENV: production

// yarn build5 NODE_ENV=production --mode development
// index 打印 process.env.NODE_ENV: development

总结

  • cross-env: 它是运行跨平台设置和使用环境变量(Node中的环境变量)的脚本。

  • --mode: 可以在任意模块内通过 process.env.NODE_ENV 获取当前的环境变量,但无法在 node 环境(webpack 配置文件中)下获取当前的环境变量

  • DefinePlugin: 允许在 编译时 将代码中的变量替换为其他值或表达式。可以在任意模块内通过 process.env.NODE_ENV 获取当前的环境变量,但无法在 node 环境(webpack 配置文件中)下获取当前的环境变量