這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
背景
大家在日常開發中應該經常會有需要切換不同環境地址的情況,當一個專案代碼切換環境地址時,vue-cli沒有能夠感知檔案的變化,所以代理的還是舊的地址,所以通常我們需要執行npm run serve進行專案重跑,而專案重跑往往意味著長時間的等待,非常痛苦!

方案調研
事實上,其實我們只是需要重啟webpack為我們啟動的proxy代理服務,或許能夠從webpack的代理服務插件中找到解決方法,

從webpack官網可以看到proxy服務其實是由 http-proxy-middleware提供的,或許我們能夠從中找到解決方法,
初步方案
在http-proxy-middleware的配置選項中,除了我們常見的target,還有router,router回傳一個字串的服務地址,當兩個選項都配置了的情況下,會優先使用router函式的回傳值,只有當router的回傳值不可用時,才會使用target的值,
我們可以利用這一點來重新配置我們的專案代碼,參考檔案在這里
// vue.config.js
const { defineConfig } = require('@vue/cli-service')
const { proxy } = require('./environments/proxy.js')
module.exports = defineConfig({
devServer:{
proxy
},
})
// proxy.js
const fs = require('fs')
const path = require('path')
const encoding = 'utf-8'
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 + ')')() }
const getConfig = () => { try {
return jsonParse(getContent('proxy-config.json'))
} catch (e) { return {} } }
module.exports = {
proxy: {
// 介面匹配規則自行修改
'/api': {
// 這里必須要有字串來進行占位
// 如果報錯Invaild Url,將target改成有效的url字串即可,如http://localhost:9001
target: 'that must have a empty placeholder',
changeOrigin: true,
router: () => (getConfig() || {}).target || ''
}
}
}
// proxy-config.json
{ "target": "http://localhost:9001" }
自此,當我們需要修改環境地址時,只需要修改proxy-config.json檔案便能夠實時生效,不再需要npm run serve!
重點代碼分析
實作代碼中其實最主要的就是getContent這個方法,我們專案在每次發起http請求時都會呼叫router中的函式,而getContent則會通過node的fs服務,對我們的環境地址檔案進行實時讀取,從而指向我們最新修改的環境地址,
方案總結
在按照參考檔案配置了專案代碼之后,我們發現確實能夠及時指向新的環境地址,再也不需要重啟代碼,不需要長時間的等待了,但是,我們多了兩個需要維護的檔案,每次我們修改環境地址時,不僅需要修改config中的api,還需要修改proxy-config.json中的target!
有沒有可能在只需要修改config檔案的情況下,實作代理地址動態修改呢?
方案優化
從上面的重點代碼分析中,可以看到只要我們可以在router函式執行時,拿到正確的config檔案中匯出的api屬性的值,也可以實作同樣的效果!
這是不是意味著只要我們在函式中對config檔案進行require請求,讀取api的值,再return出去就能及時修改代理指向了呢?
沒錯,你會發現無論你怎么修改,函式內require取到的api永遠是不變的,還是服務剛啟動時的環境地址,

參考原始碼可以知道,這是因為我們在使用require請求檔案資訊時,node會決議出我們傳入的字串的檔案路徑的絕對路徑,并且以絕對路徑為鍵值,對該檔案進行快取,


因此,如果我們在執行require函式時打斷點進行觀察的話,會發現require上面有一個cache快取了已經加載過的檔案,

這也恰恰說明了只要我們能夠洗掉掉檔案保存在require中的快取,我們就能夠拿到最新的檔案內容,那么我們也可以據此得出我們的最終優化方案,
// vue.config.js
const hotRequire = modulePath => {
// require.resolve可以通過相對路徑獲取絕對路徑
// 以絕對路徑為鍵值洗掉require中的對應檔案的快取
delete require.cache[require.resolve(modulePath)]
// 重新獲取檔案內容
const target = require(modulePath)
return target
}
...
proxy: {
'/api': {
// 如果router有效優先取router回傳的值
target: 'that must have a empty placeholder',
changeOrigin: true,
// 每次發起http請求都會執行router函式
router: () => (hotRequire('./src/utils/config') || {}).api || '',
ws: true,
pathRewrite: {
'^/api': ''
}
}
}
自此,我們專案修改環境地址將不在需要重啟專案,也不需要維護額外的檔案夾,再也不需要痛苦等待了!
本文轉載于:
https://juejin.cn/post/7198696282336313400
如果對您有所幫助,歡迎您點個關注,我會定時更新技術檔案,大家一起討論學習,一起進步,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/547963.html
標籤:其他
上一篇:pdf.js 使用

