devServe = http://localhost:3000;
prodServe = http://localhost:4000;

1. 在vue.config.js文件中,配置代理服务

使用vue/cli@5创建的项目,默认会创建vue.config.js文件,如果项目中没有此文件,那么就手动在项目根路径创建vue.config.js文件。

const { defineConfig } = require('@vue/cli-service');
const createProxy = require('./dynamic_proxy');
module.exports = defineConfig({
    transpileDependencies: true,
    devServer: {
        proxy: {
            '/': {
                target: '',
                ws: false,
                changeOrigin: true,
                router: () => {
                    return createProxy();
                }
            }
        }
    }
});

2. 在项目根路径创建文件夹dynamic_proxy,并创建proxy.list.json文件以及index.js文件。

proxy.list.json

[
    {
        "name": "devServe",
        "ip": "http://xxx.xxx.xxx.xxx:3001",
        "active": true
    },
    {
        "name": "prodServe",
        "ip": "http://xxx.xxx.xxx.xxx:3000",
        "active": false
    }
]

index.js

const { readFileSync } = require('fs');
const { resolve } = require('path');
const getProxyList = () => {
    try {
        const proxyList = readFileSync(resolve(__dirname, './proxy.list.json'), 'utf-8');
        return JSON.parse(proxyList);
    } catch (error) {
        throw new Error(error);
    }
};
const getActiveProxy = () => {
    try {
        const proxyList = getProxyList();
        if (proxyList.some(i => i.active)) {
            return proxyList.find(i => i.active);
        }
    } catch (error) {
        throw new Error(error);
    }
};
module.exports = () => {
    return getActiveProxy().ip;
};

3. 运行命令 npm run serve

4. 需要切换服务时,直接修改proxy.list.json中的active选项,修改为true,就可以自动切换了

5. 原理解析

  • vue cli 的代理是使用的http-proxy-middleware包,所以proxy选项的配置也是基于这个包的配置。在proxy配置选项中有两个属性target以及router。其中target是默认的代理地址。而router可以return一个字符串服务地址,那么当两个选项都配置了时,http-proxy-middleware在解析配置时,会首先使用router函数的返回值,当router的返回值不可以用时,那么就会fallback至target。

http-proxy-middleware router配置源码
vue/cli 配置动态代理,无需重启服务

配置校验源码
vue/cli 配置动态代理,无需重启服务

  • 可以由上面源码看出首先会校验配置,如果targetrouter都不存在的话,就会直接Error,从第一张图片源码可以看出,如果router存在的话,则会直接新建一个newTarget,并且将options.target赋值为newTarget
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。