一個前端工程從開發到上線務必會運行在多種環境中,同時會對環境變量進行相應的配置,若是使用人力去對這些變量進行維護,那麼必然會出現錯誤,因此這個功能交給 webpack 去作最爲合適。html
webpack配置項中有一個mode選項,可配置的有 production development 兩個選項,標識此次打包是用於什麼模式,在項目代碼中可以使用以下代碼進行讀取:前端
if (process.env.NODE_ENV === 'production') {
BASE_URL = 'https://host/production/api'
} else if (process.env.NODE_ENV === 'development') {
BASE_URL = 'https://host/development/api'
}
複製代碼
使用此方式,能夠分別對生產和開發模式的api分別進行配置,而不須要每次打包都進行修改,若是須要向進程中添加其它的變量,那麼能夠使用 webpack.DefinePlugin 來進行個性化定製,使用方式以下:vue
// webpack.base.js
const webpack = require('webpack')
webpackConfig = {
plugins: [
new webpack.DefinePlugin({
SOME_CONFIG: `"localhost"`
})
]
}
複製代碼
其中須要注意的一點是 '"localhost"', 若是是定義一個字符串,那麼須要雙重引號包裹。webpack
若是使用vue cli3進行項目初始化,也能夠很方便的進行環境配置,具體說明請看官方說明cli.vuejs.org/zh/guide/mo…git
可是這種配置具備必定的侷限性,按照文檔來看最多隻能支持到三種環境,一旦工程超出三種運行環境,那麼 vue cli 就沒法支持到了,因此自定義一套環境配置方案更利於擴展。github
經評論的同窗提示,再仔細看了看官方文檔,貌似是能夠支持超過三種環境配置的,囧,不過這個配置思路是能夠運用到其它工程中,因此仍是保留文章。web
由於 vue cli3 對 webpack 進行了高度的封裝,因此沒辦法像 vue cli2 同樣隨意的修改源配置文件,可是 cli3 拋出了 webpack-chain 來對默認配置進行個性化定製,用法示例以下:vue-cli
// vue.config.js
chainWebpack: config => {
config.module
.rule('js')
.exclude
.add(/\.min\.js$/)
.end()
config
.output
.set('filename', `js/[name].[hash:8]-v${__VERSION__}.js`)
.set('chunkFilename', `js/[id].[hash:8]-v${__VERSION__}.js`)
}
複製代碼
在進行配置以前,先看看 vue cli 對於環境變量這一塊是如何配置的, 在工程根目錄運行:npm
vue inspect > output.jsjson
會生成一個output.js文件,打開後滾動到最底部,在1080行左右能夠看到這樣一個配置:
/* config.plugin('define') */
new DefinePlugin({
'process.env': {
NODE_ENV: '"development"'
}
})
複製代碼
修改這個配置,就能向進程中添加其它的環境變量。
最近在使用 egg.js 時感覺到了 egg 環境變量配置帶來的便利,具體看這裏,因而決定模仿egg的作法,將此方案集成到 vue cli3 中。
對於配置的修改後面再進行講解,先講解如何區分不一樣的環境。對於環境的區分,能夠在運行打包命令時預先設定一個標籤,這裏能夠使用 cross-env 來進行設置 vue cli 的環境變量,代碼示例以下:
{
"scripts": {
"serve": "cross-env run_server=development vue-cli-service serve -mode development",
"build": "npm run build:dll && cross-env run_server=production vue-cli-service build --no-clean",
"build:UAT": "npm run build:dll && cross-env run_server=uat vue-cli-service build --no-clean",
}
}
複製代碼
這裏爲 run_server 定義了三種不一樣的值 development、 production、 uat,分別對應不一樣的服務環境,那麼在打包時,只要運行不一樣的 script 腳本就能獲取到相關的環境變量並添加到構建進程中。
在工程根目錄創建以下文件:
簡單的配置示例:
// development_server.json
{
"VUE_APP_RUN_ENV": "DevelopmentServer",
"SERVER_IP": "/api",
"DEV_PORT": 80,
"SERVER_DOMAIN": "www.google.com",
"PROXY_TARGET_IP": "http://192.168.2.236:8989"
}
複製代碼
在 vue.config.js 中添加以下代碼
const RUN_SERVER = process.env.run_server || 'development'
const DefaultENVConfig = require('./env_config/default.json')
const serverEnvConfig = Object.assign({}, DefaultENVConfig, require('./env_config/' + RUN_SERVER + '_server.json'))
複製代碼
經過傳入的目標環境,獲取到對應的配置文件。同時使用 Object.assign 函數,將目標環境配置與默認環境配置合併獲得最終的環境變量配置,再使用 webpack-chain 將之寫入webpack打包配置:
// vue.config.js
module.exports = {
chainWebpack: config => {
config.plugin('define').tap(args => {
for (let i in serverEnvConfig) {
args[0]['process.env'][i] = `"${serverEnvConfig[i]}"`
}
return args
})
}
}
複製代碼
就這樣,很簡單的代碼實現了多環境配置,若是須要添加一個全新的環境,那麼只須要添加一個配置文件,同時將配置文件名設置到打包命令中就好了。