乐趣区

Webpack多城市部署前端差异化配置实现

公司的项目需要多城市部署,不同城市接口地址、相关服务地址都会不同;同时,还需要实现控制不同城市部分功能开启 / 关闭。这样一来,每次不同城市发包需要修改的地方就会比较多且分散,这样就很容易出现疏漏。所以,我们将不同城市差异化配置单独使用一个配置文件整合,代码中再通过读取配置文件来实现上述需求。项目使用 vue-cli@2.9.6 创建;node 版本:v8.11.1;。我们一开始执行不同的脚本命令,配置不同的环境参数,来实现不同城市的区分。如下:
通过运行不同命令读取不同配置
第一步,在 package.json 的 scripts 添加脚本设置环境参数

“script”: {

“dev:changsha”: “webpack-dev-server –inline –progress –env=changsha –config build/webpack.dev.conf.js”,
“build:changsha”: “node build/build.js –env=changsha”
}

第二步,使用 yargs 在 build.js、webpack.dev.conf.js 读取环境参数并添加到 process.env

// build/build.js

const argv = require(‘yargs’).argv;
process.env.cityName = argv.env

// build/webpack.dev.conf.js

const argv = require(‘yargs’).argv;
process.env.cityName = argv.env

注意:这里因为 build 脚本是使用的 node 命令,而 node 命令是可自行添加任意参数的,即可以使用任意变量名做为环境参数;但 webpack-dev-server 命令却只支持使用 –env 选项配置环境参数。这里 build 也使用了 env 变量来设置环境参数。但是你也可以这样添加 build 脚本:
“build:changsha”: “node build/build.js –cityName=changsha”
然后在 build.js 使用相应的变量读取:
const argv = require(‘yargs’).argv;
process.env.cityName = argv.cityName

第三步,通过 webpack 读取不同城市的配置文件
在./config 文件夹下添加 changsha,chengdu 两个文件夹,分别在两个文件夹中添加 dev.conf.js、prod.conf.js。例如:
// ./config/changsha/dev.conf.js
module.exports = {
apisIp:'”http://192.200.115.1:8080″‘,
videoIp:'”http://192.200.115.2:8080″‘,
openFun1: true,
openFun2: true

}
// ./config/changsha/prod.conf.js
module.exports = {
apisIp:'”http://192.200.141.1:8080″‘,
videoIp:'”http://192.200.141.2:8080″‘,
openFun1: true,
openFun2: false

}
然后./config 下的 prod.env.js、dev.env.js 分别读取 prod.conf.js、dev.conf.js 配置
// 修改./config/dev.env.js 为
‘use strict’
const prodEnv = require(‘./prod.env’)
const cityConf = require(`./${process.env.cityName||’chengdu’}/dev.conf.js`)
module.exports = Object.assign(prodEnv, {NODE_ENV: ‘”development”‘}, cityConf)
// 修改./config/dev.env.js 为
‘use strict’
const cityConf = require(`./${process.env.cityName||’chengdu’}/prod.conf.js`)
module.exports = {
NODE_ENV: ‘”production”‘,
…cityConf
}
注意:

prod.env.js、dev.env.js 都默认加载 chengdu 文件下相应的配置;
之所以在 prod.env.js、dev.env.js 中加载相应配置就会生效,是因为在 webpack.prod.conf.js、webpack.dev.conf.js 两个文件中分别读取前两个文件;webpack.dev.conf.js 就是开发环境的入口文件;打包的入口文件 build.js 读取了 webpack.prod.conf.js;

webpack.dev.conf.js 和 webpack.prod.conf.js 都是使用 DefinePlugin 插件将环境配置写入 process.dev 的。所以,你也可以使用其它变量名保存配置;同时,你也可以不通过 prod.env.js、dev.env.js 读取配置,可以直接在 webpack.dev.conf.js、webpack.prod.conf.js 中读取;

Node.js 有一个 process 全局变量,webpack 也会生成一个 process, 这两个只是名称相同,但并不是同一个对象;前一个 process 只能 webpack 读取,我们在具体的前端代码中是无法读取的;后一个为 webpack 供给前端代码读取的全局变量,打包后 webpack 会将所有调用 prcess 的代码直接替换为具体的值;

最后,在具体前端代码中读取使用
// 例如,在./src/components/HelloWorld.vue 中,我们可以这样使用:
<template>
<div class=”hello”>
<video><source :src=”videoIp +’/a.mp4′”/></video>
<div v-if=”openFun1″> 放开功能 1 入口 </div>
<div v-if=”openFun2″> 放开功能 2 入口 </div>
</div>
</template>

<script>
const apisIp = process.env.apisIp
export default {
name: ‘HelloWorld’,
data () {
return {
videoIp: process.env.videoIp,
openFun1: process.env.openFun1,
openFun2: process.env.openFun2
}
},
methods: {
getData () {
this.$axios.get(apisIp + ‘/apis/daga’)
.then((data) => {console.log(data) })
}
}
}
</script>

总结
最后,总结梳理一下思路,大概是以下几步:

通过命令行参数写入环境参数;
将环境参数保存全 node 全局变量 process 的 env 对象上;
webpack 根据环境参数读取相应配置并写入一个全局变量供代码读取;
具体代码中,通过读取上一步定义的全局变量,实现相关功能;

退出移动版