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的弹出框插件
Mar 18 Javascript
javascript动态加载二
Aug 22 Javascript
Jquery实现显示和隐藏的4种简单方式
Aug 28 Javascript
Jquery获取和修改img的src值的方法
Feb 17 Javascript
谈谈js中的prototype及prototype属性解释和常用方法
Nov 25 Javascript
分享jQuery封装好的一些常用操作
Jul 28 Javascript
如何利用模板将HTML从JavaScript中抽离
Oct 08 Javascript
微信小程序 扎金花简单实例
Feb 21 Javascript
微信小程序实现发送验证码按钮效果
Dec 20 Javascript
Vue中的循环及修改差值表达式的方法
Aug 29 Javascript
vue中touch和click共存的解决方式
Jul 28 Javascript
openlayers实现地图测距测面
Sep 25 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
用 PHP5 轻松解析 XML
2006/12/04 PHP
解析php php_openssl.dll的作用
2013/07/01 PHP
PHP获取ip对应地区和使用网络类型的方法
2015/03/11 PHP
简单解析PHP程序的运行流程
2016/06/23 PHP
yii 2.0中表单小部件的使用方法示例
2017/05/23 PHP
JQuery扩展插件Validate—6 radio、checkbox、select的验证
2011/09/05 Javascript
基于jQuery的获取标签名的代码
2012/07/16 Javascript
jQuery.query.js 取参数的两点问题分析
2012/08/06 Javascript
IE8的JavaScript点击事件(onclick)不兼容的解决方法
2013/11/22 Javascript
利用jQuery实现可以编辑的表格
2014/05/26 Javascript
Javascript字符串对象的常用方法简明版
2014/06/26 Javascript
JS判断变量是否为空判断是否null
2014/07/25 Javascript
JavaScript数组对象赋值用法实例
2015/08/04 Javascript
举例讲解JavaScript substring()的使用方法
2015/11/09 Javascript
jQuery实现的图片轮播效果完整示例
2016/09/12 Javascript
javascript实现二叉树的代码
2017/06/08 Javascript
JavaScript设计模式之策略模式详解
2017/06/09 Javascript
vue教程之toast弹框全局调用示例详解
2020/08/24 Javascript
基于vue-cli创建的项目的目录结构及说明介绍
2017/11/23 Javascript
纯JS实现可用于页码更换的飞页特效示例
2018/05/21 Javascript
JS加密插件CryptoJS实现的Base64加密示例
2020/08/16 Javascript
Node.js Koa2使用JWT进行鉴权的方法示例
2018/08/17 Javascript
VUE路由动态加载实例代码讲解
2019/08/26 Javascript
在Python中定义一个常量的方法
2018/11/10 Python
jupyter notebook 调用环境中的Keras或者pytorch教程
2020/04/14 Python
使用Python三角函数公式计算三角形的夹角案例
2020/04/15 Python
致100米运动员广播稿
2014/02/14 职场文书
4s店销售经理岗位职责
2014/07/19 职场文书
成本会计岗位职责
2015/02/03 职场文书
首都博物馆观后感
2015/06/05 职场文书
2016年村党支部公开承诺书
2016/03/24 职场文书
市语委办2016年第十九届“推普周”活动总结
2016/04/05 职场文书
详解Python如何批量采集京东商品数据流程
2022/01/22 Python
面试中老生常谈的MySQL问答集锦夯实基础
2022/03/13 MySQL
Python中time标准库的使用教程
2022/04/13 Python
Docker安装MySql8并远程访问的实现
2022/07/07 Servers