深入掌握Proxy代理的实战技巧与应用陷阱

UE丶桠豪 前端 阅读 3,020
赞 27 收藏
二维码
手机扫码查看
反馈

Proxy代理这玩意儿,真不是随便配个路径就完事

做前端这几年,只要项目一上规模,躲不开的就得搞 Proxy。尤其是现在前后端分离成了标配,本地开发时请求后端接口跨域,不整点代理根本没法干活。我试过好几种方案,从 webpack-dev-server 的 proxy 到 Vite 的 server.proxy,再到 Nginx 和中间层 Node 服务转发。今天就来唠唠这几个方案在我实际项目里到底谁更扛造。

深入掌握Proxy代理的实战技巧与应用陷阱

结论先甩前面:日常开发我基本只用 Vite 的 proxy,简单项目够用,配置也清爽;上线或复杂路由场景下,Nginx 是唯一靠谱的选择;至于自己搭 Express 做中间层?除非你有特殊逻辑要处理,否则纯属给自己找活干。

谁更灵活?谁更省事?

先说最常用的——Vite 的内置 proxy。这玩意儿在 vite.config.js 里配一下就完事,适合大多数本地开发场景。比如你要把所有以 /api 开头的请求代理到后端服务:

// vite.config.js
export default {
  server: {
    proxy: {
      '/api': {
        target: 'https://jztheme.com',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^/api/, ''),
      },
    },
  },
}

就这么几行,启动 dev server 后访问 /api/user 就自动转到 https://jztheme.com/user。我特别喜欢它的原因是:快、轻、不用额外进程。改完保存,HMR 热更新连带着代理规则也生效了,完全无感。

但这里有个坑我踩过两次:changeOrigin 不设为 true 的时候,某些后端服务会因为 Host 头不对直接 403。尤其是对接老系统或者 Java 后台时,别图省事,这个一定要打开。

webpack 那套也能用,但我已经忘了怎么写了

说实话,自从切到 Vite 后,我已经很久没碰 webpack-dev-server 的 proxy 配置了。虽然原理差不多:

// webpack.config.js
devServer: {
  proxy: {
    '/api': {
      target: 'https://jztheme.com',
      changeOrigin: true,
      pathRewrite: { '^/api': '' },
    },
  },
}

看着是不是跟 Vite 差不多?是挺像,但问题在于 webpack 启动慢啊兄弟。一个中型项目热启动就得七八秒,每次改配置都想砸键盘。而且一旦你用了多入口或者 SSR,这套代理容易出诡异问题,比如 historyApiFallback 和 proxy 冲突,折腾半天发现是顺序问题……太累了。

所以我的态度很明确:新项目一律 Vite,老项目能迁就迁,不能迁就忍着。反正 webpack 的 proxy 能干的事,Vite 都能干,还更快。

Nginx:上线必用,开发可选

到了部署环节,你就不能再依赖开发服务器的 proxy 了。生产环境必须用 Nginx 做反向代理。这不是为了装逼,而是稳定性、安全性和性能的硬性要求。

server {
  listen 80;
  server_name app.jztheme.com;

  location /api {
    proxy_pass https://jztheme.com;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
  }

  location / {
    root /var/www/html;
    try_files $uri $uri/ /index.html;
  }
}

这段配置我在至少五个项目里复制粘贴过,稳定运行一年多没出过问题。Nginx 的优势在哪?高并发处理、静态资源缓存、HTTPS 终止、IP 限流、负载均衡……这些都是开发服务器根本不具备的能力。

但你也别指望拿 Nginx 搞本地开发代理。配一次要重启服务,日志还得手动 tail,改个路径都要 sudo 权限,开发效率直接打五折。所以我一般只在两种情况下用 Nginx 做本地代理:一是测试部署配置是否正确,二是模拟真实线上环境排查跨域或 header 问题。

Express 中间层:杀鸡用牛刀

还有些团队喜欢起一个 Express 服务专门做代理转发,甚至加身份验证、数据聚合、日志埋点……听着挺高级,实则过度设计。

const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');

const app = express();

app.use('/api', createProxyMiddleware({
  target: 'https://jztheme.com',
  changeOrigin: true,
  pathRewrite: { '^/api': '' },
  onProxyReq: (proxyReq, req, res) => {
    // 可以在这里 inject headers
    proxyReq.setHeader('Authorization', 'Bearer xxx');
  }
}));

这种方案确实灵活,你想在转发前加 token、改 body、记录日志都行。但问题是:这些逻辑真的该放在前端代理层吗?如果你只是做个 H5 页面调 API,那大可不必。但如果你们是微前端架构,或者要做 mock + 代理混合模式,那这个方案就有价值了。

我自己只在一个项目里用过这种结构:那个项目需要根据用户角色动态切换后端网关地址,普通静态 proxy 搞不定,只能走代码逻辑判断。其他时候?能省一层是一层。

我的选型逻辑

我现在是怎么选的?一句话总结:开发阶段用 Vite proxy,上线一律 Nginx,其他都是临时方案

  • 新项目初始化,vite.config.ts 里先把 proxy 配好,10 分钟搞定。
  • 联调阶段如果遇到复杂 header 或 cookie 问题,会临时搭个 Nginx 容器本地跑,验证配置。
  • 上线前把 Nginx 配置交给运维,或者写进 CI/CD 脚本,确保和开发一致。
  • Express 中间层?除非业务需求逼我,否则绝不主动上。

还有一个细节很多人忽略:环境一致性。我见过太多“我本地能跑,上预发就 404”的情况,原因就是本地用的是 Vite proxy,而预发 Nginx 配置少了个斜杠重写规则。所以建议把 Nginx 配置也纳入版本管理,甚至用 Docker Compose 本地模拟一套简化版,避免环境差异背锅。

踩坑提醒:这三点一定注意

最后分享三个我亲历的坑,希望能帮你少熬俩夜:

  1. CORS 不是代理能解决的:你用 proxy 把请求转出去了,但后端如果不带 Access-Control-Allow-Origin 头,浏览器照样报跨域。尤其是预检请求(OPTIONS)被拦截的时候,别瞎改前端配置,去查后端。
  2. WebSocket 代理要单独配:Vite 和 webpack 的 proxy 默认不处理 ws 协议,你要显式写出来:
    '/ws': {
          target: 'wss://jztheme.com',
          ws: true,
          changeOrigin: true,
        }
  3. 不要在 proxy 里做业务逻辑:看到有人用 proxy 中间件给每个请求加 userId,说是方便调试。结果 QA 测混了环境,往正式库写了一堆脏数据。代理就该干净,别搞副作用。

以上是我的对比总结,有不同看法欢迎评论区交流

Proxy 这东西看起来简单,真用起来细节一堆。我没有追求“完美方案”,只求够用、稳定、别耽误上线。Vite 满足了我的日常需求,Nginx 守住了生产底线,其他的都是备胎。

当然,如果你公司有统一网关、API Mesh 或者 Service Worker 层做代理,那是另一套玩法。那种架构我不熟,也不敢乱评。但对于大多数中小型项目来说,上面这套组合拳已经足够打了。

这文章写完我都困了,又是回忆那些通宵调代理的夜晚。希望对你有点帮助。如果有更好的实践,比如怎么优雅地管理多环境代理配置,也欢迎留言聊聊。

本文章不代表JZTHEME立场,仅为作者个人观点 / 研究心得 / 经验分享,旨在交流探讨,供读者参考。
发表评论

暂无评论