10月19, 2017

create-react-app的proxy说明

前两天,同事来说我说:后端服务拆分,现在前端一个项目,里面的请求需要对应多个不同的后端URL,它create-react-app好像是做不到的,要怎么搞?(但事实上这个脚手架是可以做到的,然后我也没去看,相信了同事说的)。

一开始我们这边为了防止组员间接口URL冲突,是单独把后端URL放在了.env文件中,且不提交。

所以现在的问题是转化成了要怎么在env中配置,比如说将其写成这样的:

myProxy=["URL1", "URL2", ...]

翻源码

于是我先打算看一下源码,再来决定怎么做。

create-react-app代理最终还是会跑到webpack-dev-server中去:

alt

在这里我知道了,devServer肯定是可以支持到数组的。

于是继续翻start.js,里面有一句:

const proxyConfig = prepareProxy(proxySetting, paths.appPublic);

alt

当看到:

if (typeof proxy !== 'object' && typeof proxy !== 'string') {
     // dosomething
}

内心是喜悦的,于是回过来去翻create-react-react的proxy文档,发现里面就有提到多个代理要怎么配。

(就这个事,值得我反思,有时候宁愿去百度看人家的二手货,也不愿意去看官方的资料,当然懒是一方面,有时候可能来缘于对英文的恐惧感)。

.env配置

整明白了这个用法,似乎就简单了。我个人先尝试在package.json下面新加一个proxy的key:

{
    "proxy": {
          "/api/*": {
            "target": "http://localhost:1521",
            "secure": false,
            "changeOrigin": true
          },
          "/apiTest/*": {
            "target": "http://localhost:1521",
            "secure": false,
            "changeOrigin": true
          }
    }
}

当然上面的target里面的URL配置理应是不一样的,我当时为了测试方便,就将其改为一样。

随后测试,是能正常通过的。

那么为了防止组员间代理URL的冲突,接下去是要放.env里面。

我当时的写法是这样的:

myProxy = {
  "/api/*": {
    "target": "http://localhost:1521",
    "secure": false,
    "changeOrigin": true
  },
  "/apiTest/*": {
    "target": "http://localhost:1521",
    "secure": false,
    "changeOrigin": true
  }
}

然后在源码中试图通过JSON.parse将其转成json,然后转入。思路没错,但错在了dotenv这个库解析key value键值对只会找一行,然后就变成了myProxy={

也就是说,我必须先把这个json压缩成一行,然后写上去。

myProxy.json配置

于是我又想到一条路,就是在文件夹下再新建一个myProxy.json,将多配置丢到里面去。

对我来说,在工具中也要实现这一套。为了统一和向下兼容,做以下约定:

  • 优先读取package.json的proxy
  • 上面读不到,去.env读取myProxy,这个是考虑字符串的形式
  • 再读取不到,就去读取myProxy.json

在实际编码中,遇到了几个问题:

  • require一个json文件,它里面必须给一个默认的空对象,而不能是空文件
  • 走到第三步(即myProxy.json)时,如果它是空对象,最终要将proxySetting变为null。

判断空对象,我用了取巧的方式:(直接判断key数组长度是否为0)

Object.keys(obj).length === 0

一些特别的注意事项

一开始我认为proxy的字符串写法和json写法是没啥区别的。

但实际测试中,如果是字符串的写法,那么直接访问URL,是得不到任何结果的。

This way, when you fetch('/api/todos') in development, the development server will recognize that it’s not a static asset, and will proxy your request to http://localhost:4000/api/todos as a fallback. The development server will only attempt to send requests without text/html in its Accept header to the proxy.

用json写法是可以的,它就是类似转发请求。

本文链接:www.my-fe.pub/post/create-react-app-proxy.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。