背景

前端开发在调试 api 阶段,或者在 fix bug 时, 常常会遇到须要一直切换代理环境的问题, 很让人头大。所以一个灵便的代理逻辑能让你省去好几支烟的功夫。

上面记录一次我的项目中代理的进化计划。

初始代理计划

通过环境变量来确定代理方向环境,

const getEndpoint = () => {  switch (process.env.EP) {    case 'qa':      return 'https://qa.xxx.cn';    case 'online':      return 'https://xxx.cn';    case 'dev':      return 'https://test.xxx.cn';    default:      return 'http://dev2.xxx.cn';  }};module.exports = {  '/api': {    target: endpoint,    changeOrigin: true,    headers: {      Host: new URL(endpoint).hostname    }  }};

react-scripts 默认失效的代理文件 /src/setupProxy.js:

module.exports = function(app) {  Object.entries(apiProxyConfig).forEach(([key, value]) => {    app.use(key, proxy(value));  });};

这种形式,在开发环境启动的过程中就确定了代理环境,且启动后无奈扭转代理环境, 除非批改环境变量,重启服务。当业务模块一直减少,开发环境启动的工夫也越来越长,每次须要频繁切换环境验证 bug 时, 就会很耗时间。

所以须要进化一下,帮咱们省一支烟的工夫。

进化后代理计划

介绍 modheader

Chrome 浏览器扩大,次要用来 增加/批改/删除申请和响应头依据URL Pattern来只对特定网站失效,等等用法。如下图,详见modheader。

原理

通过浏览器对申请信息的劫持再编辑,通过读取申请头自定义增加的值来确定代理的环境, 这样就把代理环境的做成动静的,可通过浏览器插件自定义切换代理环境了。

module.exports = function (app) {  const map = new Map();  Object.entries(apiProxyConfig).forEach(([key, value]) => {    app.use(key, (req, res, next) => {      const endpoint = req.headers['x-api-endpoint'];      if (endpoint && /^https?:\/\//.test(endpoint)) {        let handler = null;        if (map.has(endpoint)) {          handler = map.get(endpoint);        } else {          handler = createProxyMiddleware({            target: endpoint,            changeOrigin: true,            headers: {              Host: new URL(endpoint).hostname            },            pathRewrite: '^/api'          });          map.set(endpoint, handler);        }        const path = req.url;        const prefix = '/api';        // eslint-disable-next-line no-console        console.log(`[Proxy] /api${path} => ${endpoint}${prefix}${path}`);        return handler(req, res, next);      }      return next();    });  });};

多人合作

为防止不同开发者反复配置 modheader ,须要将 modheader 配置推广之,恰好modheader反对导出和导入,如图:

所以只需一人配置,分享链接给其他人导入即可应用。

本地 mock 数据

本地 mock 和代理环境并存。

module.exports = function (app) {  const mockFile = resolve(__dirname, '../mock/mock.js');  if (existsSync(mockFile)) {    apiMocker(app, mockFile);  }  const map = new Map();  Object.entries(apiProxyConfig).forEach(([key, value]) => {    // ...  })}

后记

以上计划目前齐全能满足开发需要,且不便易用。

欢送大家评论你们业务中的前端环境代理。


更简单的代理,举荐文章如下:

一文搞定前端代理骚操作!再也不怕线上bug啦!