Vue-cli3 - 讀取yaml檔並寫入env

最近新專案使用 vue-cli3 來建構,
原本預設專案內的一堆 webpack 的設定檔都消失了,
要在專案根目錄底下自己建立一個 vue.config.js 來設置。

記錄一下一些基本設定跟讀環境設定檔(yaml格式)的方法:

用vue-cli3開的專案原本那些 webpack 的設定已經被包裝好了,
vue.config.js的使用方法基本上就可以想像成覆寫,
有額外要做或調整的就在這份檔案中調整。

基本調整

例如原本我們經常會修改當 npm run dev 時的 port 及輸出的 path:

1
2
3
4
5
6
7
module.exports = {
baseUrl: '/',
outputDir: '../public/', // 輸出目錄
devServer: {
port: 9700 // local server port
}
}

就只要這樣寫就好了,要注意 vue-cli3 是使用 npm run serve 來執行 server

另外要注意,vue-cli3 執行 npm run build 後會先把輸出目錄內的東西都刪除再建立,
意味著原本可能有其他的資料夾、文件也會一併被刪除,為了要避免這情形要修改一下執行指令:
把 build 指令後面加上 --no-clean

1
2
/* package.json */
"build": "vue-cli-service build --no-clean"

其實官方文件寫的滿多預設調整的方式,可以參閱vue-cli3配置參考

讀取yaml檔

不同的環境部署通常都有不同的設定檔來做配合,
像是 API 會依據不同環境 development, staging, production 等..有不同的路徑。
舉例:

1
2
3
4
5
6
7
8
9
development:
SHOP: http://127.0.0.1:3000
CART: http://127.0.0.1:5000
staging:
SHOP: http://staging-shop.com
CART: http://staging-cart.com
production:
SHOP: http://production-shop.com
CART: http://production-cart.com

不同的環境中可能會用一份api_urls.yml來提供前後端做設定,
查看 package.json 發現已經有載入js-yaml了,就直接拿來搭配 node.js 的 fs 用:

1
2
3
4
5
6
7
8
9
/* vue.config.js */
const yaml = require('js-yaml')
const fs = require('fs')
// 讀取yaml, 會先轉為Object
const apiUrlObject = yaml.safeLoad(fs.readFileSync('../config/api_urls.yml', 'utf8'))
// 判斷當前環境
const currentEnv = process.env.ENV || 'development'
// 取出當前環境對應的資料
const currentApiUrls = JSON.stringify(apiUrlObject[currentEnv])

寫入 env 原本再 vue-cli2 時是透過 DefinePlugin 來寫入:

1
2
3
new webpack.DefinePlugin({
'process.env': env
})

vue-cli3 時要透過 chainWebpack 來做寫入 env:

1
2
3
4
5
6
7
8
9
10
11
12
13
/* vue.config.js */
module.exports = {
// ...
chainWebpack: config => {
config.plugin('define').tap(definitions => {
Object.assign(definitions[0]['process.env'], {
name: '"vuejs"',
ApiUrls: currentApiUrls
})
return definitions
})
}
}

參考 vue-cli3#chainWebpack

接著就可以在專案中可以透過 process.env 來存取部署時寫入的資訊了

1
2
const shopApiUrl = process.env.ApiUrls.SHOP
const cartApiUrl = process.env.ApiUrls.CART

這樣就可以透過讓前後端專案使用同一份設定檔,
避免同一份設定寫兩次了 :D