专栏名称: 表示很不蛋定
目录
相关文章推荐
今天看啥  ›  专栏  ›  表示很不蛋定

前端配置本地代理方法总结

表示很不蛋定  · 掘金  ·  · 2018-12-08 05:45
阅读 116

前端配置本地代理方法总结

在前后端分离的开发中,前端的静态资源存于本机上,通过 localhost 访问,如果直接调用服务端 api 则会因为跨域的问题不能正常访问。解决跨域问题可以通过 JSONP 或者让服务端设置 Access-Control-Allow-Origin 解除限制。但是并不是所有接口都可以这么搞的,所以一般需要前端自己配置代理来解决跨域问题。

背景

最近接手了一个项目,代理配置过程很有意思,记录下来。简单描述下场景:projectA 是一个普通的页面,但里面部分区域和部分弹层是通过 iframe 的形式引用的 projectB,而且后端接口限制出于安全考虑 只接受来自指定域名 (*.server.com) 的请求,对于来自 localhost 或者 IP 的请求会被直接重定向至 server 域的登陆接口(server.com/login)。需要同时启动 projectA(localhost:8087)和 projectB(localhost:8085)两个项目。

devServer.proxy大法

前端配置代理最常用的就是利用webpack的devServer.proxy了。

我首先尝试的是在 projectA 的 devServer 中这样配置:

devServer: {
        proxy: {
            '/api': {  // 需要直接代理到线上环境的接口
                target: 'http://ad.server.com',
                changeOrigin: true,
                headers: {
                    // 后端要校验请求源,那改下 host 或者 origin 不就美滋滋了?
                    Host: 'ad.server.com',
                    Origin: 'ad.server.com'
                },
            },
            '/apitest': { // 需要与后端联调的接口
                target: '10.8.0.1:9909',// 后端本地开发环境
            },

            '/iframe': {
                target: 'http://localhost:8085',
            }
            // 另外还有 iframe 里的 api 调用指向线上环境
        }
    }

复制代码

然而,后端接口残酷地给跳转到登陆接口去了 😭。猜想一下可能后端的接口是通过 cookie 来判断当前登陆域的,从 localhost 过去的请求不带 cookie。后来尝试发现在 proxy的headers里再增加 cookie 即可破跳转,但是请求过去返回结果还是在报错,后端表示仍然是认证失败。

SwitchyOmega

既然从 localhost 访问不行那只好就从 server.com 这个域来访问了。简单的做法就是利用浏览器插件 SwitchyOmega 配置代理。即 http://ad.server.com/* 的所有请求全部指向 localhost8087, http://ad.server.com/iframe/* 的请求全部指向 localhost8085, 然后将 api 的部分拎出来直接代理回线上。

switchOmega 基础配置

坑爹的是有的静态资源也不需要被代理到本地,例如 http://ad.server.com/static/* 本地可能根本就没有,得重新指回到线上。这时候 iframe 里的 projectB 又开始作妖了,里面的静态资源存于好几个目录,得挨着挨着配置,最后出来的完整配置就变得无比长。

SwitchyOmega 既可以对全局进行代理设置,也可以对单独域进行设置(点开 SwitchyOmega 看到下面那个漏斗便是)。这就导致了我的噩梦:期间我在做其他项目的时候进行一些小流量测试也是在用这个 SwitchyOmega 代理,也会涉及到对 server.com 域的修改,几番折腾后已经分不清到底当前是在全局代理还是对单独域代理了(而且实际项目中不止 server.com 这一个域),每日疑惑便是:“现在到底把哪个域代理到哪去了?”

为了避免这种困惑最后只能左手一个 Chrome,右手一个 Canary(Chrome 的开发版),两个不同浏览器分别独立的 SwitchyOmega 配置。

Charles

后来感觉用 SwitchyOmega 这种上网工具来做开发不太专业,而且切换浏览器来代理的做法也实在不方便,就改用 Charels。开启代理后利用其 Map Remote 功能,可以配置具体哪些请求代理到哪个地方去。因为其界面是图形化的,功能也比较强大,把 SwitchyOmega 里的配置抄一份过来便可用了。比 SwitchyOmega 相比,不用再把本就应该代理到线上的静态资源再写一遍,所以配置会少一些。

charels map remote 配置

最后让我放弃 Charles 的原因是:实在太卡了 😭。同时配置了多个 url 代理的情况下,电脑风扇转得飞起,请求一个被代理了的 url 半天回不了结果。而且 SwitchyOmegaCharles 都不能批量复制修改,得一个一个在图形界面改,有的时候就很麻烦(比如将线上环境切到后端的开发环境)。

Nginx

想更灵活地复制修改配置,当然最理想的就是一个可编辑的配置文件了。Nginx 正好可以非常方便的修改配置文件,而且本地启一个 Nginx 进程不会像 Charels 那么耗资源。最后配置出来的 Nginx 大概长这个样子:

http:{
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    upstream localhost8083 {
        server 127.0.0.1:8083;
        keepalive 2000;
    }
    upstream localhost8087 {
        server 127.0.0.1:8087;
        keepalive 2000;
    }
    upstream rd {
        server 10.8.0.1:9909;
        keepalive 2000;
    }
    upstream server {
        server ad.server.com;
        keepalive 2000;
    }
    server {
        listen       80;
        # api接口用于和后端开发联调
        location ^~ /api/{
            proxy_pass http://rd;
            proxy_set_header Host $host:$server_port;
        }

        # 代理 projectA 的页面
        location  ~ /(path1|path2|path3)/ {
            proxy_pass http://localhost8087;
            proxy_set_header Host $host:$server_port;
        }
        # 代理 projectA 的静态资源
        location ^~ /projectA_static/ {
            proxy_pass http://localhost8087;
            proxy_set_header Host $host:$server_port;
        }
        # 代理 projectA 的 hot-update
        location ~ \.hot-update.js$ {
            proxy_pass http://localhost8087;
            proxy_set_header Host $host:$server_port;
        }

        # 代理 projectB 的 iframe 页面
        location  ~ /(path_iframe1|path_iframe2|path_iframe3) {
            proxy_pass http://localhost8085;
            proxy_set_header Host $host:$server_port;
        }
        # 代理 projectB 的静态资源
        location ^~ /projectB_static/ {
            proxy_pass http://localhost8085;
            proxy_set_header Host $host:$server_port;
        }

        # 剩下的请求正常走 server.com 线上环境
        location / {
            proxy_pass http://server;
            proxy_set_header Host server;
        }
}

复制代码

利用 Nginx 灵活的规则,可以合并一些相似的代理规则,不用像配置 Charles 那样得一个一个自己粘贴了。另外还有个好处就是可以灵活管理自己的代理环境, 如果今后再有像这种代理比较麻烦的项目,可以分别拆成两个 nginx.conf 文件,使用时指定用哪个 conf 文件即可。如果用 Charles 管理的话,所有代理都一个配置列表里面,代理多了之后会非常难以维护。

不过本机用 Nginx 代理一般得配合改 hosts 文件,在 hosts 文件里将 test.server.com(自己瞎编的一个域,这里满足 *.server.com 就能通过后端的校验) 指向 localhost即可。启动 Nginx 指定监听 80 端口,这样访问 test.server.com 的时候(实际上访问的就是 localhost:80) 就会被 Nginx 给代理了。配置好了之后,访问 ad.server.com/就是线上环境,改成 test.server.com/ 就是本机环境了,无痛切换,非常舒服。

总结

以上几种办法都在一定场景下能实现代理的需求。后来发现社区有专门的轮子 xswitchzan-proxy。不过作为前端开发,多熟悉下 CharelsNginx 也是个不错的选择。




原文地址:访问原文地址
快照地址: 访问文章快照