Vue 類的項目開發中項目結構基本都是相似於 Vue-cli 生成的方式,
這種方式開發中,最經常使用到的模式是開啓代理進行 mock 調試或遠程調試,
也就是使用了 Vue-cli 設置的配置 proxyTable
或者直接使用 Webpack-dev-server
提供的 proxy 選項。它是採用了 http-proxy 庫,因此具體配置可查看:
https://github.com/nodejitsu/node-http-proxy#optionsjavascript
利用配置的這些參數咱們能夠作更爲靈活的配置,達到更好的效果vue
假設咱們本地開發目前如下幾種狀態:java
先看下經典的proxyTable 寫法:node
proxyTable: { '/authui/': { target: target, changeOrigin: true }, '/vendor/': { target: target, changeOrigin: true } }
其中用到了 changeOrigin
字段,主要是用於改變請求的 header。細化下需求:webpack
說明:嚴格驗證 host 和普通驗證 host 區別主要在於嚴格驗證時,請求的 url 必須是遠程機器的域名,
不能直接修改請求的 header 的 host 實現,即必須在系統 host 層面配置好域名。git
分析完成具體需求好,就開始準備實現的方式。原有開發方式是執行 npm run dev
,若是咱們須要在命令行層面添加配置,
就須要設置爲 npm run dev --param=paramvalue
的方式。對於使用 npm 的 script 腳本執行的命令,
它參數的獲取沒法經過 process.env
得到,並且經過 process.env.npm_config_paramName
的方式獲取,
使用現成的命令行參數解析庫也不是很方便,但爲了省事,暫時仍是使用 npm 自帶的解析。github
請求發起過程當中須要如下幾個參數:web
而後定義代理請求自定義類型,用於配置:npm
根據須要,咱們添加如下幾個參數用於控制代理指向地址:api
總結一下(序號指向前面的需求):
這麼一看,貌似 host 是不須要的,它的存在主要是針對某些 機器可能須要使用 host 的方式,因此仍是保留一下。
邏輯理清了就很簡單了,配置文件設置爲:
module.export = { rd1: { host: 'dev1.example.com', port: 8838, receiver: 'http://1.1.1.1:8888/receiver' }, rd2: { host: 'dev2.example.com', port: 8838, receiver: 'http://1.1.1.1:8888/receiver' } }
proxyTable 配置方式
{ proxyTable: { '/api1': 'remote', '/api2': 'rd2', '/auth/xx': 'local', '/other': 'http://example.com' } }
獲取 proxyTable 的代碼:
// 處理 proxyTable const releaseConfig = require('../config/release.conf.js') const rdConfig = releaseConfig[process.env.npm_config_rd] const isAllRemote = process.env.npm_config_focus const useHost = isAllRemote || process.env.npm_config_host // 是否本機開發,本機開發 remote 會指向 local const isAllLocal = process.env.npm_config_allLocal module.exports = function (proxy) { const localUrl = `http://localhost:${proxy.localProxyPort}` const defaultHost = proxy.defaultRdHost || 'dev-example.com' const localProxyPort = proxy.localProxyPort || 8787 const finalConfig = formatReleaseConfig(releaseConfig) const remote = finalConfig.remote || {} if (process.env.npm_config_rd) { if (!rdConfig) { throw new TypeError('RD 機器名稱不存在,請在 config/release.conf.js 中進行配置') } if (!remote.ip) { throw new Error('請配置 rd 機器的 receiver') } } if (isAllRemote && !rdConfig) { throw new TypeError('focus 只能在提供了 rd 名稱後可設置') } function formatReleaseConfig (config) { const result = {} Object.keys(config).map((key) => { const value = config[key] const ipMatch = (value.receiver || '').match(/:\/\/(.*?):\d/) const ip = ipMatch && ipMatch[1] result[key] = { ip, host: value.host || defaultHost, port: value.port || '8391' } }) // 設置 remote if (rdConfig) { const ipMatch = (rdConfig.receiver || '').match(/:\/\/(.*?):\d/) const ip = ipMatch && ipMatch[1] result.remote = { ip, host: rdConfig.host || defaultHost, port: rdConfig.port || '8391' } } // 設置 local result.local = { ip: 'localhost', host: 'localhost', port: localProxyPort } return result } function setProxy (proxyTable) { const result = {} Object.keys(proxyTable).forEach((api) => { let type = proxyTable[api] const isCustomType = typeof type === 'string' && !/^http/.test(type) if (isCustomType && type !== 'remote' && type !== 'local' && !finalConfig[type]) { throw new TypeError(`代理類型${type}不正確,請提供 http 或 https 類型的接口,或者指定正確的 release 機器名稱`) } if (type === 'remote' && !finalConfig.remote) { type = 'local' } if (isCustomType) { if (isAllRemote && type !== 'remote') { type = 'remote' } if (isAllLocal && type !== 'local') { type = 'local' } } const targetConfig = finalConfig[type] let target = type if (targetConfig) { target = { target: `http://${useHost ? targetConfig.host : targetConfig.ip}:${targetConfig.port}`, // 使用 host 時須要轉換,其餘不須要轉換 headers: { host: `${targetConfig.host}:${targetConfig.port}` } } } result[api] = target }) return result } return { proxyTable: setProxy(proxy.proxyTable), host: remote.host || defaultHost } }
用法中須要配置兩種指向:系統 host 和瀏覽器代理 Host。
之因此要兩種 host, 本質上是由於接口使用的域名
和咱們的本地訪問的域名是相同的,同一域名沒法指向兩個地址,因此至關於對瀏覽器端進行了攔截。
系統 host 推薦使用 switchHost 進行切換,瀏覽器推薦使用 whistle 進行切換。
host 配置:無
whistle 配置:默認的域名
127.0.0.1 dev.example.com
啓動命令:
npm run dev npm run dev --allLocal
注: 此時 proxyTable 中配置的 remote 所有轉換爲 local,在 allLocal 參數時將全部自定義類型轉換爲 local
host 配置:無
whistle 配置:默認的域名
127.0.0.1 dev1.example.com 127.0.0.1 dev2.example.com
啓動命令:
npm run dev --rd=rd1 npm run dev --rd=rd1 --host
注: --host 表示使用訪問使用 host 而非 ip,使用時須要 host 地址
host 配置:無
whistle 配置:默認的域名
127.0.0.1 dev1.example.com 127.0.0.1 dev2.example.com
proxyTable 配置:
{ proxyTable: { '/api1': 'rd1', '/api2': 'rd2', '/auth/xx': 'local', '/other': 'http://example.com' } }
啓動命令:
npm run dev
host 配置:
1.1.1.1 dev1.example.com 1.1.1.1 dev2.example.com
whistle 配置:默認的域名
127.0.0.1 dev1.example.com 127.0.0.1 dev2.example.com
啓動命令:
npm run dev --rd=rd1 --focus
細挖需求,可能還有更簡單的方式,在大部分狀況下可以減小代碼修改,
是 webpack 配置型的實現吧。固然,方式並不完美,尤爲在 mac 下,
竟然不能支持 --rd xx
這種形式,能夠有相似的庫吧,後續能夠作爲深刻的內容