在我们开发前端应用中,往往需要使用多个环境,例如
1.本地开发环境
2.测试环境
3.正式环境
所以每个环境都需要对相应的服务器地址、环境专属变量等做出单独的配置。
我们使用vue-cli init生成的项目,调试与打包已经为我们在package.json中做好了。
/* /package.json */
"scripts": {
"dev": "webpack-dev-server --inline --host 0.0.0.0 --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"e2e": "node test/e2e/runner.js",
"test": "npm run e2e",
"build": "node build/build.js",
}
* 之前遇到的问题:本地调试 localhost:8080 可正常访问,但是使用本机ip(http://192.168.*.*:8080)无法访问;
解决方法:在package.json中dev命令加上 0.0.0.0 ;
* 这里想特别说明一下的是,vue-cli脚手架帮我们生成好了整个项目,而且也有对应webpack.dev.conf.js和webpack.prod.conf.js两个分离的webpack配置文件,但由于文件的命名问题(dev.conf.js/prod.conf.js),很容易让人误以为这两个文件就是webpack针对不同环境的配置。但实际上这两个文件一个是用于本地调试时的配置文件,另一个是用于打包部署的配置文件。调试/打包两种模式 与 环境(dev/test/pre/prod等)是可以相互组合的。理论上来讲这两个webpack的配置文件我觉得应该叫webpack.debug.conf.js和webpack.build.conf.js会更贴切一点。
通过yargs可以方便的获取指定名称的命令行参数,它是node.js中的一个组件,可以通过npm直接安装。
$ npm install yargs --dev --save
/* hello.js */
const argv = require('yargs').argv;
console.log('hello ', argv.env);
/* 命令行 */
$ node ./hello.js --env test
hello test
接下来就要看看如何利用这个参数实现多文件配置。
Webpack中可以使用DefinePlugin插件来配置我们的环境
/* /build/webpack.dev.conf.js: */
plugins: [
new webpack.DefinePlugin({
// 源码中所有 process.env 都会被替换为
// '../config/dev.env'这个module export出来的东西
'process.env': require('../config/dev.env')
})
]
/* /config/dev.env.js */
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"'
})
我们可以通过上面传入到脚本中的环境参数,动态加载不同环境的配置文件,以达到切换环境的目的。动态加载不同配置环境的代码:(/build下新建webpack.env.conf.js)
/* /build/webpack.env.conf.js */
// 定义参数配置
const argv = require('yargs').argv;
// 获取环境变量
const env = argv.env;
process.stdout.write('the env is '+ env +'\n');
// require指定的环境配置文件
const envConfigFile = "../config/" + env + ".env.js";
process.stdout.write('the env config file is '+ envConfigFile +'\n');
// 将require的配置文件原封不动export回出去
module.exports = require(envConfigFile);
接下来要将动态加载的环境文件丢到webpack的配置文件中,由于webpack.dev.conf.js和webpack.prod.conf.js都是继承自webpack.base.conf.js,所以我们直接改写wepack.base.conf.js的插件配置部分,直接添加DefinePlugin插件的配置,并去掉原配置文件该插件的配置:
/* /build/webpack.base.conf.js */
// 引入上面的webpack.env.conf模块
const envConfig = require('./webpack.env.conf')
module.exports = {
...
,
// 配置DefinePlugin插件
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': envConfig
})
],
...
}
然后调试/打包的命令我们可以这样写:
/*/package.json*/
"scripts": {
"dev": "webpack-dev-server --inline --host 0.0.0.0 --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"e2e": "node test/e2e/runner.js",
"test": "npm run e2e",
"build": "node build/build.js",
"start:dev": "webpack-dev-server --inline --host 0.0.0.0 --progress --config build/webpack.dev.conf.js --env dev",
"start:test": "webpack-dev-server --inline --host 0.0.0.0 --progress --config build/webpack.dev.conf.js --env test",
"start:prod": "webpack-dev-server --inline --host 0.0.0.0 --progress --config build/webpack.dev.conf.js --env prod",
"build:dev": "node build/build.js --env dev",
"build:test": "node build/build.js --env test",
"build:prod": "node build/build.js --env prod"
},
几个环境配置的内容:
/* /config/test.env.js */
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"testing"',
API_HOST:'"http://*.*.*.*:8580/"' //测试环境
})
/* /config/prod.env.js */
'use strict'
module.exports = {
NODE_ENV: '"production"',
API_HOST:'"http://*.*.*.*:8580/"' //生产环境
}
/* /config/dev.env.js */
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"',
API_HOST: '"/api"' //开发环境
})
* 这里dev环境配置里的API_HOST为什么要写成 '"/api"',我们等下说到跨域再讲。
这样我们就可以通过process.env.NODE_ENV来获取各个环境的参数值(dev/test/prod)
在api模块中可以这样写:
/* /src/api/index.js */
const API_HOST = process.env.API_HOST;
export default API_HOST
然后,在我们的Vue组件中就可以很方便的使用这些环境配置了:
/* /src/components/HelloWorld.vue */
import api_host from '@/api'
data () {
return {
msg: 'Welcome',
env: process.env.NODE_ENV,
api_host: api_host,
}
}
最后,使用各自命令打包发布各个环境:
# serve with hot reload at localhost:8080
npm run start:dev
npm run start:test
npm run start:prod
# 发布测试环境:
npm run build:test
# 发布正式环境:
npm run build:prod
# 设置API_HOST, PATH: ./config/*.env.js
API_HOST:'"http://*.*.*.*:8580/"'
我们在本地开发调试后台给的接口(后台未配置跨域)时,不同ip之间的访问,往往有跨域问题。
Vue-cli 创建的项目,可以直接利用 Node.js 代理服务器,通过修改vue proxyTable接口实现跨域请求。
在vue-cli项目中的config文件夹下的index.js配置文件中,修改当前的dev:
/* /config/index.js */
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/api': { //代理地址(适用于开发环境)
target: 'http://10.10.*.*:8580',//设置你调用的接口域名 别忘了加http
changeOrigin: true, //是否跨域
pathRewrite: {
'^/api': '/'//这里理解成用‘/api’代替target里面的地址,后面组件中我们调接口时直接用api代替 比如我要调用'http://10.10.*.*:8580/rank/info/?rankid=23784&page=1&json=true',直接写‘/api/rank/info/?rankid=23784&page=1&json=true’即可
}
}
},
}
前文提到dev环境配置里的API_HOST为什么要写成 '"/api"',就在于此,改成代理地址即可跨域访问接口
/* /src/api/api.js */
import axios from 'axios'
import urls from './url'
import api_host from '@/api'
// 定义axios基本设置
const request = axios.create({
baseURL: api_host
})
export default () => {
return {
async getData (obj) {
return handleRequest(await request.post(urls.testUrl, obj))
},
async getJSON(){
return handleRequest(await request.get(urls.testJson, {}))
}
}
}
参考博文:Webpack下多环境配置的思路、vue-cli项目开发/生产环境代理实现跨域请求+webpack配置开发/生产环境的接口地址