• 只要等一等就能多“等”出8600万美元! 2019-01-23
  • 长颈鹿在中国高纬度地区成功繁育 小鹿刚出生一米八 2019-01-23
  • 今天十一选五开奖结果:Vue 项目代理设置的优化

    3d开奖结果走势图连线 www.fwrl.net

    Vue 项目代理设置的优化


    Vue 项目代理设置的优化

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

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

    使用需求

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

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

    方案

    先看下经典的proxyTable 写法:

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

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

    1. 本地开发:target 指向 localhost 的某个端口即可。至于 host 的验证肯定是不需要的
    2. 部分本地,其他固定的一台远程机器:需要配置 localhost 和远程的地址,远程地址多半是需要验证 host 的
    3. 同二,但机器有多台:需要手动配置多台机器
    4. 同一台远程机器,此时机器可能要严格验证,即 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: 指定的远程机器
    • 其他自定义类型:用于在配置文件中已经指定的其他类型
    • 原版本的请求,如 "//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: "//1.1.1.1:8888/receiver"
      },
      rd2: {
        host: "dev2.example.com",
        port: 8838,
        receiver: "//1.1.1.1:8888/receiver"
      }
    }

    proxyTable 配置方式

    {
      proxyTable: {
        "/api1": "remote",
        "/api2": "rd2",
        "/auth/xx": "local",
        "/other": "//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 = `//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: `//${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 配置:

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

    启动命令:

    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

    总结

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

    当前文章://www.fwrl.net/news/20180870392.html

    发布时间:2019-03-25 00:27:19

    欢乐斗地主残局破解大全 天天tv安卓版下载 真人德扑圈吧 可兑现金的捕鱼游戏 乐乐作文网官网 日本麻将单机版下载 成都隆诚装饰 手机软件大全 德扑起手牌打法 酷乐棋牌

    编辑:邓丁宗

      

    Comments are closed.

  • 只要等一等就能多“等”出8600万美元! 2019-01-23
  • 长颈鹿在中国高纬度地区成功繁育 小鹿刚出生一米八 2019-01-23