最近新接了一個項目歪今,需要在啟動時選擇代理到不同的后端地址株婴,我就想到用 inquirer 做命令選擇
- inquirer 引用代碼
// inquirer 版本 5.2.0
function ask() {
var proxys = require('./serverProvider')
return inquirer.prompt([
{name: 'prefix', type: 'input', message: '請輸入prefix(如果有)'},
{name: 'target', type: 'list', message: '請選擇代理的地址', choices: Object.values(proxys)}
])
.then(answers => {
app.use(proxyMiddleware(answers['prefix'], {
target: answers['target'],
changeOrigin: true
}))
resolve()
})
.catch(e => {
reject(e)
})
}
- serverProvider 文件
module.exports = {
provider1: '172.27.49.11:8081', // 小明
provider2: '172.27.49.10:8081', // 小紅
}
執(zhí)行 npm run dev
后揖铜,報錯:
WX20180425-162106@2x.png
解決問題
- 看到所屬包是
requires-port
, 調(diào)用該包的庫是http-proxy-middleware
, 看到該包版本為0.17.3柏肪,就想著是不是版本太低的 bug姐刁,逐使用npm update | grep http-proxy-middleware
,發(fā)現(xiàn)最新也就0.17.4烦味,基本可排除版本問題聂使。 - 那就看該庫哪里報錯吧,根據(jù)提示找到
node_models/requires-port/index.js
13行
module.exports = function required(port, protocol) {
protocol = protocol.split(':')[0];
...
}
可以看到是傳進(jìn)來的protocol為空谬俄,所以執(zhí)行 split 操作時報錯(其實(shí)細(xì)心點(diǎn)這時已經(jīng)可以知道錯誤在哪了)
然后在node_models全局搜'requires-port'(或者看報錯第二行)柏靶,定位到node_models/http-proxy/lib/http-proxy/common.js 109行
if (options.changeOrigin) {
outgoing.headers.host =
required(outgoing.port, options[forward || 'target'].protocol) && !hasPort(outgoing.host)
? outgoing.host + ':' + outgoing.port
: outgoing.host;
}
是options[forward || 'target'].protocol為undefined,所以導(dǎo)致調(diào)用 requires-port 出錯溃论,打印出 options 后發(fā)現(xiàn)是 target: xxxx
屎蜓,是個 String 類型,之后將這個改為含有protocol的對象就正常執(zhí)行了钥勋。
后續(xù)
發(fā)現(xiàn)之前項目也是target為String的炬转,但沒有報錯,對比后發(fā)現(xiàn)原來是寫的后端地址沒有寫上協(xié)議(心酸~~)算灸,補(bǔ)充后String類型也是可以的扼劈。
還有一個關(guān)于inquirer的補(bǔ)充吧,因?yàn)楹蠖说刂番F(xiàn)在是對象的形式菲驴,只能獲取value荐吵,但不能在選擇的時候就與是哪個同事的地址匹配,所以改成Map形式
// 更改后的serverProvider
const map = new Map()
map.set('小明', '172.27.49.11:8081')
map.set('小紅', '172.27.49.10:8081')
// TODO 可以做成一個類赊瞬,添加validate方法校驗(yàn)
module.exports = Array.from(map)
// 修改引用代碼
function ask() {
var proxys = require('./serverProvider')
return inquirer.prompt([
{name: 'prefix', type: 'input', message: '請輸入prefix(如果有)'},
{name: 'target', type: 'list', message: '請選擇代理的地址', choices: proxys.map(it => String(it))}
])
.then(answers => {
app.use(proxyMiddleware(answers['prefix'], {
target: answers['target'].split(',')[1],
changeOrigin: true
}))
})
}
總結(jié)
這個錯誤其實(shí)是一個低級錯誤先煎,不應(yīng)該犯的,將這篇文章寫出來是為了分享我的問題解決方式森逮,如有哪些地方可以改進(jìn)的也可以留下評論榨婆。