vue動態代理無須重啟專案解決方案

語言: CN / TW / HK

1.背景

當我們vue構建專案的時候,都會在vue.config.js中配置我們需要代理的伺服器地址。有時候我們需要使用不同後端伺服器地址,也就是我們開發中所說的測試環境、灰度環境、正式環境等,這個時候如果我們需要使用不同的環境地址的時候,就需要使用命令或者手動修改vue.config.js中配置來重新啟動專案。當專案專案越來越大的時候,我們需要很長的時間來啟動專案,如此反覆,極大影響我們開發進度。這個時候我們急需一種vue動態代理無須重啟專案解決方案來提高我們的開發專案,以此為背景,萌生出了以下方案。

2.技術方案

2.1 舊的配置方案

我們在vue.config.js中常用的代理方案如下: js const port = process.env.port || process.env.npm_config_port || 80 // 埠 module.exports = { lintOnSave: false, devServer: { host: '0.0.0.0', port, open: false, proxy: { '/my-api': { target: 'https://www.baidu.com', ws: false, changeOrigin: true, } } } } 在啟動專案的時候,只會讀取一次配置檔案,當再次修改target地址時,vue-cli是無法感知檔案的變化,所以代理的還是舊的地址,所以我們需要重新啟動專案來使配置生效。有沒有一種方案,可以在修改配置的時候能使vue-cli感知到檔案的變化,從而讀取新的配置呢?方案入下:

2.2 新的配置方案思路

vue-cli 的代理是使用的http-proxy-middleware包,所以proxy選項的配置也是基於這個包的配置。在proxy配置選項中有兩個屬性target以及router。其中target是預設的代理地址。而router可以return一個字串服務地址,那麼當兩個選項都配置了時,http-proxy-middleware在解析配置時,會首先使用router函式的返回值,當router的返回值不可以用時,那麼就會fallback至target。

http-proxy-middleware router配置原始碼 image.png

配置校驗原始碼 image.png

我們可以使用proxyrouter來讀取我們的代理配置檔案,這樣就可以實現修改代理配置檔案來更新代理地址,無須啟動專案。

3. 配置

vue.config.js中加入如下配置: ```js // vue.config.js const dynamicProxy = require('./environments/proxy.js') const port = process.env.port || process.env.npm_config_port || 80 // 埠

module.exports = { lintOnSave: false, devServer: { host: '0.0.0.0', port, open: false, proxy: dynamicProxy.proxy, disableHostCheck: true }, } 新建`environments`資料夾,同時在裡面新建`proxy.js`檔案js // proxy.js const fs = require('fs') const path = require('path')

const encoding = 'utf-8' /* * 獲取配置檔案內容 getContent('proxy-config.json') * @param filename env.json * @returns {string} / const getContent = filename => { const dir = path.resolve(process.cwd(), 'environments') return fs.readFileSync(path.resolve(dir, filename), { encoding }) }

const jsonParse = obj => { return Function('"use strict";return (' + obj + ')')() }

/ * 獲取配置選項 getConfig() * @returns {{}|} / const getConfig = () => { try { return jsonParse(getContent('proxy-config.json')) } catch (e) { return {} } }

module.exports = { proxy: { // 介面匹配規則自行修改 ['/my-api']: { target: 'that must have a empty placeholder', // 這裡必須要有字串來進行佔位 changeOrigin: true, router: () => (getConfig() || {}).target || '' } } } ``proxy.js最後匯出一個物件,這個物件跟我們以前使用的舊代理方案很像,但是多了一個router配置router函式返回執行getConfig`函式讀取配置檔案的內容,也就是我們的代理地址。

environments目錄下新建我們的代理配置檔案proxy-config.jsonjson { "target": "https://www.baidu.com" } 當專案啟動後,會讀取我們的代理配置檔案。我們在專案啟動後,手動修改代理配置檔案的代理地址,然後重新整理頁面,就可以使我們的新代理地址生效。

4. 示例demo

https://github.com/atdow/vue-dynamic-proxy-demo