内容简介:在前后端分离的开发中,前端的静态资源存于本机上,通过 localhost 访问,如果直接调用服务端 api 则会因为跨域的问题不能正常访问。解决跨域问题可以通过 JSONP 或者让服务端设置最近接手了一个项目,代理配置过程很有意思,记录下来。简单描述下场景:前端配置代理最常用的就是利用webpack的devServer.proxy了。
在前后端分离的开发中,前端的静态资源存于本机上,通过 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 调用指向线上环境 } } 复制代码
然而,后端接口残酷地给跳转到登陆接口去了 :sob:。猜想一下可能后端的接口是通过 cookie 来判断当前登陆域的,从 localhost 过去的请求不带 cookie。后来尝试发现在 proxy的headers里再增加 cookie 即可破跳转,但是请求过去返回结果还是在报错,后端表示仍然是认证失败。
SwitchyOmega
既然从 localhost 访问不行那只好就从server.com 这个域来访问了。简单的做法就是利用浏览器插件 SwitchyOmega
配置代理。即 http://ad.server.com/*
的所有请求全部指向 localhost8087, http://ad.server.com/iframe/*
的请求全部指向 localhost8085, 然后将 api 的部分拎出来直接代理回线上。
坑爹的是有的静态资源也不需要被代理到本地,例如 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
相比,不用再把本就应该代理到线上的静态资源再写一遍,所以配置会少一些。
最后让我放弃 Charles 的原因是:实在太卡了 :sob:。同时配置了多个 url 代理的情况下,电脑风扇转得飞起,请求一个被代理了的 url 半天回不了结果。而且 SwitchyOmega
和 Charles
都不能批量复制修改,得一个一个在图形界面改,有的时候就很麻烦(比如将线上环境切到后端的开发环境)。
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/
就是本机环境了,无痛切换,非常舒服。
总结
以上几种办法都在一定场景下能实现代理的需求。后来发现社区有专门的轮子 xswitch 、zan-proxy。不过作为前端开发,多熟悉下 Charels
和 Nginx
也是个不错的选择。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 前端路由&webpack基础配置
- 前端快速入门Nginx配置
- AngularJS + CoffeeScript 前端开发环境配置详解
- AngularJS + CoffeeScript 前端开发环境配置详解
- 从0搭建前端项目架构-webpack配置
- 前端小纠结--VS Code调试配置分享
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。