问题背景
工作中两个场景都需要将stg和prod环境的前端代码中不同的接口url 以及各种外部引用的url等提取到静态变量中,并且更改静态变量的配置url就可以改变网站的访问接口
场景一:做docker自动部署平台的时候,当服务器的地址发生变化,后端接口迁移了,然后前端需要在平台上可以自动部署而不是手动部署的时候,就需要有一个配置文件可以在线上编辑更改。
场景二:前端是用工程化生成的,但是整体没有前后端分离部署。后端通过自动化部署的时候需要经过 获取代码---普通编译---stg部署----prd部署 步骤,后端部署stg的时候用的是前端生成的stg代码。prod的时候是prod的代码,为了在上平台上部署,需要后端编写shell脚本,区分stg和prod环境,然后将前端不同的包在不同的阶段放到服务器的根目录下。因为是整个项目的静态资源包,可能比较大,需要先zip压缩然后再解压。后端就提出,可不可以只是把不同的环境的不同的部分提取出来,然后只是移动这一个文件,就可以大大提升部署速度。
解决方案
综上:寻找出两种方法来解决
- 方法一:前端将不同环境的配置放到一个config.js中,然后通过用户访问的不同的url来区分是线上还是测试环境。每次服务器发生变化,只需要改变这个配置文件区分不同环境访问的url
- 首先在vue-cli静态文件夹 vuecli2是static文件下 vueCli3是public文件夹下新建config.js配置文件,包括不同环境的key对应的不同的接口地址等
// 在public目录下新建一个config.js文件
export consst config=[
// 接口地址
targetAddress: {
local:"http://xxx.xxx.local.com",
stg: "http://xxx.xxx.stg.com",
prod:'http://xxx.xxx.prod.com',
},
urlMap: {
local: ['10.118.120.41:8080','localhost:8080', '10.118.120.43:8089'],
stg: ['XXX.XXX.stg.com'],
prod: ['XXX.XX.prod.com'],
cas: {
local:"http://XXX.XXX.local/cas/#/",
stg: "http://XXX.XXX.stg/cas/#/",
prod:'http://XXX.XXX.prod/cas/#/',
}
},
developerUrl: {
local:"http://XXX.XXX.local/subiectallmanage/",
stg: "http://XXX.XXX.stg/subiectallmanage",
prod:'http://XXX.XXX.prod/subiectallmanage',
}
]
- 然后在项目的api接口文件中引入config配置文件,并且根据用户输入的地址判断是哪一个环境(是local还是stg还是prod),然后根据环境取出对应config中的url地址即可
// 在接口文件中 api/api.js下面写上如下代码
import { config } from '../../public/js/config.js'
let targetUrl = ''; // 后端接口Url
const curUrl = window.location.href; // 用户输入的url
const map = config.urlMap;
for (let env in map) {
if ( env != 'cas') {
let hasUrl = map[env].some(e => {
return curUrl.includes(e);
})
if (hasUrl) { targetUrl = config.targetAddress[env]; }
}
}
- 方法二:利用插件generate-asset-webpack-plugin在打包的时候生成json文件,然后通过axios请求获取json中的配置。因为后端可以区分是生产还是测试环境,所以只需要有一个默认的json文件和一个生产的json 测试的json。然后后端通过shell脚本判断当前环境替换生产json到默认json目录下面。
- 安装插件 generate-asset-webpack-plugin
npm i generate-asset-webpack-plugin -D
- vue.config.js中添加插件,使用插件生成json文件
var GenerateAssetPlugin = require('generate-asset-webpack-plugin');
var createServerConfig = function(compilation) {
// 配置需要的api接口
let cfgJson = {
VUE_APP_SERVE_URL: process.env.VUE_APP_PULIC_PATH,
VUE_APP_PULIC_ACTIVE: process.env.VUE_APP_PULIC_ACTIVE
}
return JSON.stringify(cfgJson);
}
module.exports = {
configureWebpack: {
plugins: [
new GenerateAssetPlugin({
// 不同的环境生成不同的json文件 stgConfig.json prdConfig.json
filename: `${process.env.VUE_APP_STATUS}Config.json`,
fn: function(compilation, cb) {
cb(null, createConfig(compilation))
}
})
]
}
}
- 配置完成后,运行npm run test打测试包,生成stgConfig.json文件在测试目录下,如下图
- 然后将生成的stgConfig.json改名为serverconfig.json复制一份到public下面,在src目录下面新建一个getConfigUrl.js文件
import axios from 'axios';
Vue.prototype.getConfigJson = function() {
axios.get("serverconfig.json").then((result) => {
//挂载到vue原型上面,这样就可以在项目中调用了
Vue.prototype.$configApiUrl = result.data;
console.log(result.data);
}).catch((error) => {
console.log('getConfigJson Error!', error)
})
}
- 最后将项目中用到
process.env.VUE_APP_SERVE_URL替换成 this.$configApiUrl.VUE_APP_SERVE_URL
process.env.VUE_APP_PULIC_ACTIVE替换this.$configApiUrl.VUE_APP_PULIC_ACTIVE
然后执行npm run build打包生成prdConfig.json将两个配置文件都给到后端即可。