vue工程不同环境配置文件自动切换

项目环境一般分为开发环境、测试环境、生产环境,每个环境的接口域名和其他配置、webpack配置可能都是不同的配置,每次打包构建不能总是手动去更改这些配置,我们应当根据打包的环境去动态判断不同环境自动切换配置,尤其是自动化构建部署如jenkins

使用node的fs模块实现vue-cli2中根据打包环境动态切换配置

  • 配置文件 src/common/config.js
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    // 部署不同的环境时 需要修改 DBS_ENV 的值
    // 0 开发环境 1为测试环境1 2为测试环境2 3为正式环境
    var DBS_ENV = 1
    var baseUrl = ''
    var clientId = ''
    swicth (DBS_ENV){
    case 0:
    baseUrl = 'http://192.168.5.6'
    clientId = '90'
    break
    case 1:
    baseUrl = 'http://22.11.33.44'
    clientId = '91'
    break
    case 2:
    baseUrl = 'http://22.55.33.99'
    clientId = '92'
    break
    case 3:
    baseUrl = 'https://xxx.cn'
    clientId = '93'
    break
    }
    export default {baseUrl, clientId}
  1. 修改package.json中的npm scripts的打包命令

    1
    2
    3
    4
    5
    6
    scripts: {
    "dev": "node build/dev-server.js", // 开发环境
    "build-T1": "node build/build.js", // T1测试环境1
    "build-T2": "node build/build.js", // T2测试环境2
    "build-pro": "node build/build.js" // pro生产环境
    }
  2. 在build.js中通过打包参数修改src/common/config.js文件中DBS_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
    25
    26
    27
    28
    29
    30
    31
    32
    // 读取配置文件
    const fs = require('fs')
    let fileContent = ''
    const envPath = path.resolve(__dirname, '../src/common/config.js')
    try {
    fileContent = fs.readFileSync(envPath, 'utf-8')
    } catch(error){
    console.log(chalk.red(error + '/n'))
    process.exit(1)
    }
    // 获取打包命令判断打包环境参数
    const event = process.env.npm_lifecycle_event
    let env = 1
    switch(event){
    case 'build-T1':
    env = 1
    break
    case 'build-T2':
    env = 2
    break
    case 'build-pro':
    env = 3
    break
    }
    // 根据打包参数修改配置文件并写入
    const text = fileContent.replace(/(var DBS_ENV = \d;)/, `var DBS_ENV = ${env};`)
    try {
    fs.writeFileSync(envPath, text, 'utf-8')
    } catch(error){
    console.log(chalk.red(error + '/n'))
    process.exit(1)
    }
  3. 打包完成放弃src/common.config.js修改

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    let childProcess = require('child_process')
    // 在build.js中的打包完成回调中 webpack(webpackconfig, function(){xxx})
    // svn 版本管理回退
    // childProcess.execSync('svn revert src/common/config.js', function(err, stdout, stdin){
    // console.log(chalk.red(err))
    // })
    // git 版本管理回退
    childProcess.execSync('git checkout -- src/common/config.js', function(err, stdout, stdin){
    console.log(chalk.red(err))
    })

使用cross-env和webpack.DefinePlugin()实现vue-cli2中根据打包环境动态切换配置

  • cross-env:可以跨平台设置和使用环境变量(process.env)的node模块包
  • webpack.DefinePlugin(): webpack通过DefinePlugin内置插件将process.env注入到客户端代码中,定义的变量可以在webpack打包范围内任意javascript环境内访问
  1. 修改package.json中的npm scripts的打包命令

    1
    2
    3
    4
    5
    6
    scripts: {
    "dev": "node build/dev-server.js", // 开发环境
    "build-T1": "cross-env MODE=T1 node build/build.js", // T1测试环境1
    "build-T2": "cross-env MODE=T2 node build/build.js", // T2测试环境2
    "build-pro": "cross-env MODE=pro node build/build.js" // pro生产环境
    }
  2. 修改config/dev.env.js和config/prod.env.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // config/dev.env.js
    module.export = {
    NODE_ENV: '"development"',
    MODE: '"dev"' // 全局变量
    })
    // config/prod.env.js
    module.export = {
    NODE_ENV: '"production"',
    // process.env.MODE 是通过 cross-env 设置的环境变量 即T1或T2或pro
    MODE: JSON.stringify(process.env.MODE) // 全局变量字符串需要使用JSON.stringify()
    })
  3. 在webpack.dev.conf.js和webpack.prod.conf.js通过new webpack.DefinePlugin()注入到执行环境中使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // webpack.dev.conf.js
    plugins: [
    new webpack.DefinePlugin({
    'process.env': require('../config/dev.env')
    })
    ]
    // webpack.prod.conf.js
    plugins: [
    new webpack.DefinePlugin({
    'process.env': require('../config/prod.env')
    })
    ]
  4. 配置文件动态赋值 src/common/config.js

    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
    // 通过cross-env 和 webpack.DefinePlugin() 将process.env注入到执行环境(客户端代码)中使用
    // 设置DBS_ENV 的值 0 开发环境 1为测试环境1 2为测试环境2 3为正式环境
    var DBS_ENV = ''
    var baseUrl = ''
    var clientId = ''
    const envArr = ['dev', 'T1', 'T2', 'pro']
    if (envArr.indexOf(process.env.MODE) > -1) {
    DBS_ENV = envArr.indexOf(process.env.MODE)
    }
    swicth (DBS_ENV){
    case 0:
    baseUrl = 'http://192.168.5.6'
    clientId = '90'
    break
    case 1:
    baseUrl = 'http://22.11.33.44'
    clientId = '91'
    break
    case 2:
    baseUrl = 'http://22.55.33.99'
    clientId = '92'
    break
    case 3:
    baseUrl = 'https://xxx.cn'
    clientId = '93'
    break
    }
    export default {baseUrl, clientId}
  5. 其他用处

  • 可以通过process.env.MODE设置sourceMap

    1
    2
    3
    4
    5
    // config/indx.js
    build: {
    // 生产环境关闭sourcemap(避免暴露源码) 开发环境和测试环境开启sourcemap便于调试和定位错误
    productionSourceMap: process.env.MODE === 'pro' ? false : true
    }
  • 可以通过process.env.MODE设置仅在开发环境和测试环境引入vconsole

    1
    2
    3
    4
    5
    6
    7
    // main.js 仅在开发环境和测试环境引入vconsole
    if (process.env.MODE!=='pro') {
    // 不能使用 import vConsole from 'vconsole' 或 import('vconsole') 静态引入 不能放在if里面会报错
    // SyntaxError: xxx/main.js 'import' and 'export' may only appear at the top level
    let vConsole = require('vconsole') // 使用require引入 可放在if里动态引入
    new vConsole()
    }

使用process.env.npm_config_arg|process.argv和webpack.DefinePlugin()实现vue-cli2中配置切换

process.env.npm_config_argv或process.argv可以获取npm命令行的参数,动态设置MODE,然后通过DefinePlugin注入

  1. 修改package.json中的npm scripts的打包命令

    1
    2
    3
    4
    5
    6
    7
    8
    9
    scripts: {
    "dev": "node build/dev-server.js", // 开发环境
    "build": "node build/build.js"
    }
    // 打包构建 在执行 npm run build 时多加入一个命令行参数
    /* npm run build T1 // T1测试环境1
    * npm run build T2 // T2测试环境2
    * npm run build pro // pro生产环境
    */
  2. 修改config/dev.env.js和config/prod.env.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // config/dev.env.js
    module.export = {
    NODE_ENV: '"development"',
    MODE: '"dev"' // 全局变量
    })
    // config/prod.env.js
    module.export = {
    NODE_ENV: '"production"',
    // 方式1
    // process.env.npm_config_argv->JSON字符串 获取npm命令行的参数,动态设置MODE
    // npm run build pro -> process.env.npm_config_argv -> '{"remain":["pro"], "cooked":["run", "build", "pro"],...}'
    // 全局变量字符串需要使用JSON.stringify()
    MODE: JSON.stringify(JSON.parse(process.env.npm_config_argv).remain[0])
    // 方式2
    // npm run build pro -> 使用 process.argv -> ["c:\\xxx\node.exe", "D:\\project\xx\build.js", "pro"]
    // MODE: JSON.stringify(process.argv[2])
    })
  3. 其他步骤和上个方法一致

使用自定义loader实现配置环境的切换

  1. package.json中的npm scripts的打包命令

    1
    2
    3
    4
    5
    6
    scripts: {
    "dev": "node build/dev-server.js", // 开发环境
    "build-T1": "node build/build.js", // T1测试环境1
    "build-T2": "node build/build.js", // T2测试环境2
    "build-pro": "node build/build.js" // pro生产环境
    }
  2. 配置文件 src/common/config.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    var DBS_ENV = 0
    var baseUrl = ''
    var clientId = ''
    swicth (DBS_ENV){
    case 0:
    baseUrl = 'http://192.168.5.6'
    clientId = '90'
    break
    case 1:
    baseUrl = 'http://22.11.33.44'
    clientId = '91'
    break
    case 2:
    baseUrl = 'http://22.55.33.99'
    clientId = '92'
    break
    case 3:
    baseUrl = 'https://xxx.cn'
    clientId = '93'
    break
    }
    export default {baseUrl, clientId}
  3. 自定义loader替换环境变量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //  loaders/config-loader.js
    modules.exports = function (content) {
    this.cacheable()
    if (process.env.npm_lifesycle_event === 'build-T1') {
    content = content.replace(/(var DBS_ENV = \d)/, `var DBS_ENV = 1`)
    } else if (process.env.npm_lifesycle_event === 'build-T2'){
    content = content.replace(/(var DBS_ENV = \d)/, `var DBS_ENV = 2`)
    } else if (process.env.npm_lifesycle_event === 'build-pro'){
    content = content.replace(/(var DBS_ENV = \d)/, `var DBS_ENV = 3`)
    } else {
    content = content.replace(/(var DBS_ENV = \d)/, `var DBS_ENV = 0`)
    }
    return content
    }
  4. 使用loader webpack.base.conf.js

    1
    2
    3
    4
    5
    6
    7
    8
    module: {
    rules: [
    {
    test: /config\.js$/,
    loader: path.resolve('loaders') + '/config-loader'
    }
    ]
    }

vue-cli3及以上使用不同的.env文件设置不同的环境配置

vue-cli3.x封装了webpack配置,.env文件中的变量都会被放入当process.env中,我们可以直接在客户端代码中使用process.env的值,该对象可以包含多个键值对,仅支持注入环境配置文件中以VUE_APP_开头的变量,也是通过webpack.DefinePlugin()实现

  • 在根目录下设置不同环境的配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // .env.T1 测试环境1配置
    VUE_APP_baseUrl = 'http://22.11.33.44'
    VUE_APP_clientId = 91
    // .env.T2 测试环境2配置
    VUE_APP_baseUrl = 'http://22.55.33.99'
    VUE_APP_clientId = 92
    // .env.prod 生产环境
    VUE_APP_baseUrl = 'http://xxx.cn'
    VUE_APP_clientId = 93
  • 修改package.json中的npm-script脚本的命令

    1
    2
    3
    4
    5
    6
    7
    8
    9
    "scripts": {
    // vue-cli-service build --mode=xxx webpack会去找对应的配置文件 .env.xxx
    // 测试环境1 会读取对应配置文件 .env.T1
    "build-T1": "vue-cli-service build --mode=T1",
    // 测试环境2 会读取对应配置文件 .env.T2
    "build-T2": "vue-cli-service build --mode=T2",
    // 生产环境 会读取对应配置文件 .env.prod
    "build": "vue-cli-service build --mode=prod"
    }
  • 配置变量的使用

    1
    2
    3
    4
    5
    // 客户端代码中 或 vue.config.js 中
    // 仅支持注入环境配置文件中以 VUE_APP_ 开头的变量 客户端代码中使用时,都是字符串形式
    // VUE_APP_XXX = xxx 都会被webpack.DefinePlugin()设置为 process.env = {VUE_APP_XXX: "xxx" ,...}
    config.baseUrl = process.env.VUE_APP_baseUrl
    headers.clientId = process.env.VUE_APP_clientId // process.env.VUE_APP_clientId => "93"
  • 如果需要在客户端代码中根据打包环境区分某些配置或功能如vconsole

    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
    // 方法一
    // 可以在 .env.T1 .env.T2 .env.prod 配置文件中 加VUE_APP_MODE = T1或T2或pro
    // .env.T1 测试环境1配置
    VUE_APP_MODE = T1
    VUE_APP_baseUrl = 'http://22.11.33.44'
    // .env.T2 测试环境2配置
    VUE_APP_MODE = T2
    VUE_APP_baseUrl = 'http://22.55.33.99'
    // .env.prod 生产环境
    VUE_APP_MODE = pro
    VUE_APP_baseUrl = 'http://xxx.cn'
    // 方法二 不在 .env.xxx 配置文件中写死 可以通过配置 DefinePlugin 注入 MODE
    // vue.config.js
    moudles.export = {
    chainWebpack: config => {
    config.plugin('define').tap(args => {
    //args => [{'process.env': { NODE_ENV: 'developMent', VUE_APP_base_url: 'xx'}}]
    // 通过 process.env.npm_lifecycle_script 去获取 => vue-cli-service build --mode=T1
    args[0]['process.env'].VUE_APP_MODE = JSON.stringify(process.env.npm_lifecycle_script.match(/--mode=(.+)(?=\s)/)[1])
    return args
    })
    }
    }
    // 使用 main.js 仅在开发环境和测试环境引入vconsole
    if (process.env.VUE_APP_MODE!=='pro') {
    let vConsole = require('vconsole') // 使用require引入 可放在if里动态引入
    new vConsole()
    }
-------------本文结束感谢您的阅读-------------
0%