Vue 项目代理设置的优化


Posted in Javascript onApril 17, 2018

Vue 类的项目开发中项目结构基本都是类似于 Vue-cli 生成的方式,这种方式开发中,最常用到的模式是开启代理进行 mock 调试或远程调试,也就是使用了 Vue-cli 设置的配置 proxyTable 或者直接使用 Webpack-dev-server提供的 proxy 选项。它是采用了 http-proxy 库,所以具体配置可查看:

https://github.com/nodejitsu/node-http-proxy#options

利用配置的这些参数我们可以做更为灵活的配置,达到更好的效果

使用需求

假设我们本地开发目前以下几种状态:

  • 本地开发,数据使用本地的 mock Server
  • 涉及权限接口使用本地 mock 数据,其他全部使用指定的一台远程机器
  • 涉及权限接口使用本地 mock 数据,其他数据分接口使用不同的远程机器
  • 所有接口使用同一台远程机器

方案

先看下经典的proxyTable 写法:

proxyTable: {
 '/authui/': {
  target: target,
  changeOrigin: true
 },
 '/vendor/': {
  target: target,
  changeOrigin: true
 }
}

其中用到了 changeOrigin 字段,主要是用于改变请求的 header。细化下需求:

  • 本地开发:target 指向 localhost 的某个端口即可。至于 host 的验证肯定是不需要的
  • 部分本地,其他固定的一台远程机器:需要配置 localhost 和远程的地址,远程地址多半是需要验证 host 的
  • 同二,但机器有多台:需要手动配置多台机器
  • 同一台远程机器,此时机器可能要严格验证,即 IP 也必须使用域名,配置好系统 host 才可使用

说明:严格验证 host 和普通验证 host 区别主要在于严格验证时,请求的 url 必须是远程机器的域名,
不能直接修改请求的 header 的 host 实现,即必须在系统 host 层面配置好域名。

分析完成具体需求好,就开始准备实现的方式。原有开发方式是执行 npm run dev,如果我们需要在命令行层面添加配置,就需要设置为 npm run dev --param=paramvalue 的方式。对于使用 npm 的 script 脚本执行的命令,
它参数的获取无法通过 process.env 获得,而且通过 process.env.npm_config_paramName 的方式获取,
使用现成的命令行参数解析库也不是很方便,但为了省事,暂时还是使用 npm 自带的解析。

请求发起过程中需要以下几个参数:

  • host: 发起请求需要指向的 host,可能每台机器验证并不相同
  • port: 代理转发的端口
  • receiver: 用于 push 的远程地址,内包含了 ip 地址,为了省事,没有单独列出 ip 地址

然后定义代理请求自定义类型,用于配置:

  • local: 本地地址,即 localhost
  • remote: 指定的远程机器
  • 其他自定义类型:用于在配置文件中已经指定的其他类型
  • 原版本的请求,如 'http://xxx' 或者 Object 类型的配置,此类代理永不处理

根据需要,我们添加以下几个参数用于控制代理指向地址:

  1. rd: 远程机器的地址
  2. focus: 严格模式,所有自定义类型的代理转换为指定的 rd 机器,只在存在 rd 参数时可用
  3. allLocal:自定义类型代理全部指向本地
  4. host:请求发现是否使用 host,而不是 IP 地址

总结一下(序号指向前面的需求):

  • 需要使用 host 进行访问的情形:4
  • 需要更改 host:除 localhost 外都需要更改
  • 需要对已有类型进行转换:1: 需要将所有自定义类型都转换为 local, 2和3:什么也不转换,4:所有的自定义类型全部转换为

remote 类型

这么一看,貌似 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

本地 + 1 台远程

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 地址

本地 + n 台远程

host 配置:无

whistle 配置:默认的域名

127.0.0.1 dev1.example.com

127.0.0.1 dev2.example.com

{
 proxyTable: {
  '/api1': 'rd1',
  '/api2': 'rd2',
  '/auth/xx': 'local',
  '/other': 'http://example.com'
 }
}

proxyTable 配置:

启动命令:

npm run dev

远程 1 台机器

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

组件优化

vue 的组件化深受大家喜爱,到底组件拆到什么程度算是合理,还要因项目大小而异,小型项目可以简单几个组件搞定,甚至不用 vuex,axios 等等,如果规模较大就要细分组件,越细越好,包括布局的封装,按钮,表单,提示框,轮播等,推荐看下 Element 组件库的代码,没时间写这么详细可以直接用 Element 库,分几点进行优化

•组件有明确含义,只处理类似的业务。复用性越高越好,配置性越强越好。

•自己封装组件还是遵循配置 props 细化的规则。

•组件分类,我习惯性的按照三类划分,page、page-item 和 layout,page 是路由控制的部分,page-item 属于 page 里各个布局块如 banner、side 等等,layout 里放置多个页面至少出现两次的组件,如 icon, scrollTop 等

总结

细挖需求,可能还有更简单的方式,在大部分情况下能够减少代码修改,是 webpack 配置型的实现吧。当然,方式并不完美,尤其在 mac 下,居然不能支持 --rd xx 这种形式,可以有类似的库吧,后续可以做为深入的内容。

以上所述是小编给大家介绍的Vue 项目代理设置的优化,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
用Jquery实现可编辑表格并用AJAX提交到服务器修改数据
Dec 27 Javascript
js加密解密字符串可自定义密码因子
May 13 Javascript
js对象基础实例分析
Jan 13 Javascript
网页禁用右键菜单和鼠标拖动选择方法小结
Feb 25 Javascript
javascript模拟C#格式化字符串
Aug 26 Javascript
jQuery使用each方法与for语句遍历数组示例
Jun 16 Javascript
微信小程序 下拉菜单的实现
Apr 06 Javascript
vue.js 左侧二级菜单显示与隐藏切换的实例代码
May 23 Javascript
JS实现简易的图片拖拽排序实例代码
Jun 09 Javascript
jQuery绑定事件方法及区别(bind,click,on,live,one)
Aug 14 jQuery
Android 自定义view仿微信相机单击拍照长按录视频按钮
Jul 19 Javascript
解决vue.js中settimeout遇到的问题(时间参数短效果不稳定)
Jul 21 Javascript
在 Typescript 中使用可被复用的 Vue Mixin功能
Apr 17 #Javascript
vue iview实现动态路由和权限验证功能
Apr 17 #Javascript
基于VuePress 轻量级静态网站生成器的实现方法
Apr 17 #Javascript
Vue-cropper 图片裁剪的基本原理及思路讲解
Apr 17 #Javascript
js闭包学习心得总结
Apr 17 #Javascript
Vue使用json-server进行后端数据模拟功能
Apr 17 #Javascript
js实现点击按钮复制文本功能
Jul 20 #Javascript
You might like
php+highchats生成动态统计图
2014/05/21 PHP
php视频拍照上传头像功能实现代码分享
2015/10/08 PHP
PHP 计算两个时间段之间交集的天数示例
2019/10/24 PHP
用js生产批量批处理执行命令
2008/07/28 Javascript
JS的location.href跳出框架打开新页面的方法
2014/09/04 Javascript
兼容Firefox的Javascript XSLT 处理XML文件
2014/12/31 Javascript
XML文件转化成NSData对象的方法
2015/08/12 Javascript
jQuery文字横向滚动效果的实现代码
2016/05/31 Javascript
javascript类型系统_正则表达式RegExp类型详解
2016/06/24 Javascript
ajax实现加载页面、删除、查看详细信息 bootstrap美化页面!
2017/03/14 Javascript
angular或者js怎么确定选中ul中的哪几个li
2017/08/16 Javascript
javaScript实现鼠标在文字上悬浮时弹出悬浮层效果
2020/04/12 Javascript
koa-passport实现本地验证的方法示例
2020/02/20 Javascript
JavaScript实现图片放大预览效果
2020/11/02 Javascript
Python中的面向对象编程详解(下)
2015/04/13 Python
Python实现的数据结构与算法之链表详解
2015/04/22 Python
用Python实现web端用户登录和注册功能的教程
2015/04/30 Python
python选择排序算法实例总结
2015/07/01 Python
Python的Django框架中的Context使用
2015/07/15 Python
使用Python获取网段IP个数以及地址清单的方法
2018/11/01 Python
python的pytest框架之命令行参数详解(下)
2019/06/27 Python
python常见字符串处理函数与用法汇总
2019/10/30 Python
Django import export实现数据库导入导出方式
2020/04/03 Python
浅析Python中字符串的intern机制
2020/10/03 Python
MoviePy常用剪辑类及Python视频剪辑自动化
2020/12/18 Python
html5 Canvas画图教程(11)—使用lineTo/arc/bezierCurveTo画椭圆形
2013/01/09 HTML / CSS
科颜氏美国官网:Kiehl’s美国
2017/01/31 全球购物
IFCHIC台湾:欧美国际设计师品牌
2019/05/18 全球购物
酒店办公室文员岗位职责
2013/12/18 职场文书
法人委托书范本
2014/09/15 职场文书
保研专家推荐信范文
2015/03/25 职场文书
个人工作违纪检讨书
2015/05/05 职场文书
安全生产学习心得体会
2016/01/18 职场文书
《小小的船》教学反思
2016/02/18 职场文书
干货干货!2019最新优秀创业计划书
2019/03/21 职场文书
配置Kubernetes外网访问集群
2022/03/31 Servers