# 配置(环境配置)

前言

前端项目开发中,一般会有几个环境:

  • dev:是程序员们专门用于开发的服务器,配置可以比较随意, 为了开发调试方便,一般打开全部错误报告
  • sit:dev 环境完成需求开发就可以将代码打包到 sit 环境,给测试验证相关功能
  • uat:一般是克隆一份生产环境的配置,sit 测试没有问题就可以将代码打包到 uat 环境,然后由需求提出方验收需求
  • prod:uat 环境完成需求验收就可以将代码部署到正式环境
英文缩写 英文 中文 示例 是否必须 主要用户
dev Development 开发环境 dev.zhoubichuan.com 开发
sit System Integrate Test 系统集成测试环境(内测) sit.zhoubichuan.com 功能测试
uat User Acceptance Test 用户验收测试环境 uat.zhoubichuan.com 产品
pet Performance Evaluation Test 性能评估测试环境(压测) pet.zhoubichuan.com 性能测试
sim Simulation 高仿真环境 sim.zhoubichuan.com
prod Production 生产环境 zhoubichuan.com 用户

# 1.vue-cli 2.x 中

# 1.1 配置环境

  • webpack 通过 DefinePlugin 内置插件将 process.env 注入到客户端代码中。
// config/dev.env.js
module.exports = merge(devEnv, {
  NODE_ENV: '"dev"', // 注意value值需要序列化
  BASE_API: '"http://dev.com"',
})
1
2
3
4
5
//build/webpack.dev.conf.js
const env = require('../config/dev.env')
...
{
  plugins: [
    new webpack.DefinePlugin({
      "process.env": {
        NODE_ENV: env,
      },
    }),
  ],
}
...
1
2
3
4
5
6
7
8
9
10
11
12
13
  • 不同的打包/运行命令,打包/运行不同环境代码的同时将环境变量注入到打包/运行后的代码中 package.json
...
"scripts":{
  "dev":"vue-cli-service --mode dev",
  "sit":"vue-cli-service --mode sit",
  "build:dev":"vue-cli-service build --mode dev",
  "build:sit":"vue-cli-service build --mode sit"
}
...
1
2
3
4
5
6
7
8

# 1.2 使用环境变量

// main.js
console.log("环境变量:" + process.env.NODE_ENV)
1
2

# 2.vue-cli 3.x 中

# 2.1 配置文件

原理

在根目录下创建以下形式的文件进行不同环境下变量的配置,webpack 内部会按照一定的规则加载这些文件

.env                 #在所有的环境中被载入
.env.local           #在所有的环境中被载入,但会被git忽略
.env.[mode]          #只在指定的模式中被载入,如.env.sit
.env.[mode].local    #只在指定的模式中被载入,但会被git忽略,如.env.sit.local
1
2
3
4
  • 1.配置命令

    // package.json
    "scripts":{
      "serve:dev":"vue-cli-service serve --mode dev", //npm run serve:dev,dev运行命令,默认环境 development
      "build:dev":"vue-cli-service build --mode dev" //npm run build:dev,dev打包命令,默认环境 production
    }
    
    1
    2
    3
    4
    5
  • 2.配置相关环境变量

    // env.dev
    NODE_ENV=dev
    VUE_APP_BASE_URL=http://dev.com
    VUE_APP_TITLE=宇宙管理系统
    
    1
    2
    3
    4

    注意

    配置的变量需要以VUE_APP_开头,而NODE_ENVBASE_URL这两个特殊变量除外

  • 3.使用相关环境变量

    //vue.config.js
    console.log(process.env.NODE_ENV) //dev
    
    1
    2
    //src/utils/http.js
    axios.create({
      baseURL: process.env.VUE_APP_BASE_URL, // http://dev.com
      timeout: 500,
    })
    
    1
    2
    3
    4
    5
  • 4.配置文件的权重

    由配置公共配置案例,可以得出结论,相同配置项的权重:
    • 全局公共配置

      // .env
      NODE_ENV = development;
      VUE_APP_BASE_URL=http://base.com
      VUE_APP_TITLE=地球管理系统
      
      1
      2
      3
      4

      使用后可以得到:http://dev.com

    • 本地公共配置

      // .env.local
      NODE_ENV = development;
      VUE_APP_BASE_URL=http://localhost.com
      VUE_APP_TITLE=abc管理系统
      
      1
      2
      3
      4

      使用后可以得到:http://localhost.com

    .env.[mode].local > .env.[mode] > .env.local > .env # 相同配置项权重大的覆盖小的,不同配置项它们会进行合并操作
    
    1
  • 5.配置文件的局限性

    只能配置静态变量

    veu-cli3.x 封装的 webpack 中已经完成了这个功能,但是仅支持以VUE_APP_开头的变量(NODE_ENVBASE_URL除外)

    NODE_ENV=stage2
    VUE_APP_TITLE=stage mode2
    NAME=vue
    
    1
    2
    3

    然后我们尝试在 vue.config.js 中打印process.env终端输出:

    {
      ...
      npm_config_ignore_scripts: '',
      npm_config_version_git_sign: '',
      npm_config_ignore_optional: '',
      npm_config_init_version: '1.0.0',
      npm_package_dependencies_vue_router: '^3.0.1',
      npm_config_version_tag_prefix: 'v',
      npm_node_execpath: '/usr/local/bin/node',
      NODE_ENV: 'stage2',
      VUE_APP_TITLE: 'stage mode2',
      NAME: 'vue',
      BABEL_ENV: 'development',
      ...
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    可以看到输出内容除了我们环境配置中的变量外还包含了很多 npm 的信息,但是我们在入口文件 main.js 中打印会发现输出:

    {
      "BASE_URL": "/vue/",
      "NODE_ENV": "stage2",
      "VUE_APP_TITLE": "stage mode2"
    }
    
    1
    2
    3
    4
    5

    可见注入时过滤了非VUE_APP_开头的变量,其中多出的BASE_URL为你在 vue.config.js 设置的值,默认为/,其在环境配置文件中设置无效。

# 2.2 环境注入

原理

webpack 通过 DefinePlugin 内置插件将 process.env 注入到客户端代码中。

//vue.config.js
{
  ...
  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
  • 1.配置环境变量

    .env 这样的配置文件无法使用动态参数,这时候我们可以在根目录下新建 config 文件夹用于存放一些额外的配置文件。
    // envConfig.js
    const com = {
      $Time: new Date().toLocaleString(), //注入项目打包时间信息,可以在页面加载时挂载到window上,方便查看更新时间
    }
    let config = {
      // 开发环境
      dev: {
        NODE_ENV: "dev",
        ...com,
      },
      //测试环境
      sit: {
        NODE_ENV: "sit",
        ...com,
      },
      //客户体验环境
      uat: {
        NODE_ENV: "uat",
        ...com,
      },
      // 生产环境
      prod: {
        NODE_ENV: "prod",
        ...com,
      },
    }
    Object.keys(config).forEach((item) => {
      Object.keys(config[item]).forEach((key) => {
        config[item][key] = JSON.stringify(config[item][key])
      })
    })
    module.exports = config
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
  • 2.注入环境变量

    // vue.config.js
    const envConfig = require("./envConfig")
    const merge = require("webpack-merge")
    module.exports ={
      ...
      chainWebpack:config = {
        config.plugin('define')
        .tap(args => {
          let name = 'process.env'
          let env = process.argv[process.argv.length - 1]
          args[0][name] = merge(args[0][name],envConfig[env])
          return args
        })
      }
      ...
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
  • 3.使用环境变量

    {
      "NODE_ENV":"dev",
      "VUE_APP_TITLE":"stage mode2",
      "BASE_URL":"/vue/",
      "$Time":"xxx"
    }
    
    1
    2
    3
    4
    5
    6

# 3.场景应用

# 3.1 前端调试

  • 线上bug调试,前端使用本地开发代码,后端使用线上接口
  • 通过代理的方式实现调试

# 3.2 后端调试

  • 背景:有些项目比较复杂,接口 a 依赖接口 b,接口 b 依赖接口 c,中间还有很多页面流程需要走;如果在 postman 中调试接口很麻烦,有很多页面生成的数据要自己造

  • 可以借用线上的前端开发环境,页面接口用本地的接口(直接优先使用在浏览器 localStorage 中的变量)

    // commonUrl.js
    const url = "www.xxx.com"
    if (process.env.NODE_ENV !== "production") {
      url = localStorage.url || url
    }
    
    1
    2
    3
    4
    5
  • 后端可以直接在线上dev环境中配置localStorage.url = 自己本地接口地址,方便调试

总结

在 vue-cli2.x 和 3.x 中都可以利用 DefinePlugin 来配置环境变量,这种方式的优点在于更加灵活,而在 vue-cli3.x 中还支持配置静态文件类型的配置文件(.env 文件)这种方式配置更加直观。