前端工程化(4):http-proxy-middleware在多环境下的代理应用

栏目: 后端 · 前端 · 发布时间: 5年前

内容简介:假设开发的时候存在以下几套环境:是的,就是有这么多的环境等着你去访问它们。那么跑前端代码的时候如何才能与各个环境进行联调呢?最简单直接的办法就是修改所以本文提出了一个能让你在联调时无缝切换不同环境的方案。如果你没用到代理或者后端设置了跨域资源共享,这篇文章看看也无妨。如果你用到了

假设开发的时候存在以下几套环境:

  • 自己本地的 MOCK 环境(自己造一些随心所欲的数据)

  • RAP 平台环境(与后端约定好数据格式)

  • 后端开发人员的本地环境(与后端联调)

  • 阿里云1测试环境(部署到测试环境,测试人员测试)

  • 阿里云2测试环境(环境紧张,需要部署到别的测试环境进行测试)

  • 阿里云3测试环境(公司不差钱,买了至少5个服务器)

  • 阿里云4测试环境

  • 阿里云5测试环境

    ......

是的,就是有这么多的环境等着你去访问它们。那么跑前端代码的时候如何才能与各个环境进行联调呢?最简单直接的办法就是修改 proxy 选项中的 target ,然后再重新执行开发脚本。这个方法在项目小的情况你还能忍受,如果项目大的话,过长的编译时间将直接消磨掉你的工作激情。

所以本文提出了一个能让你在联调时无缝切换不同环境的方案。如果你没用到代理或者后端设置了跨域资源共享,这篇文章看看也无妨。如果你用到了 http-proxy-middleware 来处理跨域的问题,那这篇文章你更得看看。

第一步、配置环境

定义一个变量来承载所需要的路由键值对:

测试环境

let PROXY_ROUTER = {
  'dev-aliyun1.test.com': 'https://m-aliyun1.test.com:10454',
  'dev-aliyun2.test.com': 'https://m-aliyun2.test.com:10454',
  'dev-aliyun3.test.com': 'https://m-aliyun3.test.com:10454',
  'dev-aliyun4.test.com': 'https://m-aliyun4.test.com:10454',
  'dev-aliyun5.test.com': 'https://m-aliyun5.test.com:10454'
}
复制代码

每个开发域名 dev-aliyunX.test.com 域名都对应一个测试环境。

RAP环境

let PROXY_ROUTER = {
  ...
  'dev-rap.test.com': 'http://192.168.4.102:9999/mockjsdata/400',
}
复制代码

用过 RAP 的同学都知道,不同模块挂着不同的 id (就是:point_up_2:url中的400),那这样是不是得把所需要的 id 都写上去?其实 RAP 提供了项目路由功能,能把不同模块的 id 路由到一个模块 id 上:

前端工程化(4):http-proxy-middleware在多环境下的代理应用
前端工程化(4):http-proxy-middleware在多环境下的代理应用

各个模块之间使用逗号隔开,这样只需要写一个主id就行。

后端开发本地环境

// 填写后端开发的ip地址和端口号
const devHostName = '172.16.9.xx'
const devServerPort = '8085'

let PROXY_ROUTER = {
  ...
  'dev-debug.test.com': `http://${devHostName}:${devServerPort}`
}
复制代码

与后端开发联调就避免不了要重启项目了,因为后端开发的ip未知,需要手动填写。

本地mock环境

src目录下新建 mock.js 文件,写入:

import Mock from 'mockjs' // 引入mock
import { mockMemberInfo } from './memberinfo'

Mock.mock('/api/rights/memberInfo', 'post', {
  {
    'code': '100',
    'result': {
        'level': 'trial',
        'name': '沈浩',
    },
    'resultDes': '',
    'success': true
  }
})
复制代码

main.js 中写入:

if (process.env.NODE_ENV !== 'production' && window.location.hostname.indexOf('test') < 0) {
  require('./mock.js')
}
复制代码

只有在开发环境并且是代理到本地mock的情况下才启用。无需在路由表中写入对应的环境。

注:所有的开发域名都需要配置host,如下:127.0.0.1 dev-m-aliyun1.test.com ...

第二步、配置路由

统一前缀

统一对所有的接口进行代理处理,如果用了 axios 请求库,可以这么配置:

axios.defaults.baseURL = process.env.NODE_ENV === 'production' ? '' : '/api'
复制代码

路由分发

http-proxy-middleware 提供了一个 router 选项(接收一个对象或者函数):可以使用 host 或者 path 或者 host+path 匹配特定的请求来重写 option.target ,也就是说 router 命中的 url 优先级高于 target 配置的 url

处理前缀为 /api 的接口:

let proxyTable = {
  '/api': ''
}

Object.entries(proxyTable).forEach(([key, value], index) => {
  proxyObj[key] = {
    target: value || 'http://localhost:8080',
    changeOrigin: true,
    pathRewrite (path, req) {
      return path.replace(/\/api/, '')
    },
    router (req) {
      let hostname = req.headers.host.split(':')[0]
      return value === '' ? PROXY_ROUTER[hostname] : value
    }
  }
})
复制代码

通过接口请求的 host ,来匹配 PROXY_ROUTER 中对应的环境。如果匹配上了, router function 返回匹配上的环境地址从而覆盖掉 target 。如果没匹配上, router function 返回 undefinedtarget 生效,即代理本地mock环境。

在现实开发中还可能会出现一种奇葩的需求:你在a环境联调,但有的接口还在b环境上。要解决这种问题,你只需要在 proxyTable 中加上:

let proxyTable = {
  '/api/cms/renderData': 'https://m-aliyun2.test.com:10454',
  '/api': ''
}
复制代码

这样无论你怎么切换域名, /api/cms/renderData 始终将会被代理到 https://m-aliyun2.test.com:10454 环境上。

顺序很重要,第一个匹配上的将会生效。

总结

vue-cli3 为脚手架,在根目录新建一个 proxy.config.js 文件:

let proxyObj = {}

// 与开发联调的时候由于未知 需手动填写
const devHostName = '172.16.9.xx'
const devServerPort = '8085'
// 代理路由表
let PROXY_ROUTER = {
  'dev-m-aliyun1.test.com': 'https://m-aliyun1.test.com:10454', // 代理到阿里云1测试环境
  'dev-m-aliyun2.test.com': 'https://m-aliyun2.test.com:10454', // 代理到阿里云2测试环境
  'dev-m-aliyun3.test.com': 'https://m-aliyun3.test.com:10454', // 代理到阿里云3测试环境
  'dev-m-aliyun4.test.com': 'https://m-aliyun4.test.com:10454', // 代理到阿里云4测试环境
  'dev-m-aliyun5.test.com': 'https://m-aliyun5.test.com:10454', // 代理到阿里云5测试环境
  'dev-rap.test.com': 'http://192.168.4.102:9999/mockjsdata/400', // 代理到rap环境
  'dev-debug.test.com': `http://${devHostName}:${devServerPort}` // 代理到后端开发人员的ip环境
}
// 代理接口
let proxyTable = {
  '/api/cms/renderData': 'https://m-aliyun2.test.com:10454',
  '/api': ''
}

Object.entries(proxyTable).forEach(([key, value], index) => {
  proxyObj[key] = {
    target: value || 'http://localhost:8080', // 代理到本地mock环境
    changeOrigin: true,
    pathRewrite (path, req) {
      return path.replace(/\/api/, '')
    },
    router (req) {
      let hostname = req.headers.host.split(':')[0]
      return value === '' ? PROXY_ROUTER[hostname] : value
    }
  }
})

module.exports = proxyObj
复制代码

vue.config.js 文件中修改:

const proxyBase = require('./proxy.config')

module.exports = {
  devServer: {
    proxy: proxyBase,
    disableHostCheck: true // 新版的webpack-dev-server出于安全考虑,默认检查hostname,如果hostname不是配置内的,将中断访问
  },
  ...
}
复制代码

上述代理配置以后, 只需要通过切换域名就可以无缝切换相应的测试环境,无需重启前端服务 ,这对所处多个开发环境的前端开发者来说大大提高了工作效率。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Machine Learning in Action

Machine Learning in Action

Peter Harrington / Manning Publications / 2012-4-19 / GBP 29.99

It's been said that data is the new "dirt"—the raw material from which and on which you build the structures of the modern world. And like dirt, data can seem like a limitless, undifferentiated mass. ......一起来看看 《Machine Learning in Action》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

随机密码生成器
随机密码生成器

多种字符组合密码

MD5 加密
MD5 加密

MD5 加密工具