Vite的proxy和Nginx的location 请求转发区别

你的疑问?

vite

复制代码
proxy: {
  '/api/': {
    target: baseUrl,
    changeOrigin: true,
    rewrite: (p) => p.replace(/^\/api/, '')
  }
}

nginx

location /api/ {

加上这个斜杠,效果等于 Vite 的 rewrite

proxy_pass http://你的Java服务器内部IP:8080/;

标准配置:把真实的客户端信息传给 Java

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;

}

vite的代理,既然最后都要把它删掉,为什么还要费劲巴拉地先加上去,然后再用正则删掉?这看起来简直像是在玩"脱了袜子放屁"的游戏。

其实,这并不是多此一举,而是一个非常精妙的路由分发信号

为了让你彻底理解,我给你打个比方。

1. 核心原因:区分"文件"和"接口"

假设你的前端项目(Vite)是一个巨大的公司。

  • 静态资源部 :负责处理 .js, .css, .png, index.html(这些是真实存在你硬盘里的文件)。

  • 外联部(Proxy) :负责把请求发给后端大厨(Java 接口)。

如果你直接请求 localhost:5173/getsingelUser/1,Vite 会怎么想? Vite 会去你的硬盘里找:"咦?我的文件夹里有一个叫 getsingelUser/1 的文件吗?" 找了一圈没找到,它就会报 404。

所以,我们需要一个"标志"。

当你请求 /api/getsingelUser/1 时:

  1. Vite 一看 :哦!路径开头是 /api

  2. 触发判断 :它知道这不是找本地文件的,而是要交给"外联部"转发的。

  3. 开始转发 :外联部接手后,发现后端大厨其实不认识 /api 这个暗号。

  4. 执行 Rewrite :为了不让大厨懵逼,外联部贴心地把 /api 抹掉,变成大厨认识的 /getsingelUser/1 发过去。


2. 如果不配置 /api 会发生什么?

如果你想尝试"省掉"这一步,直接把 proxy 配置成匹配所有路径(比如 /):

JavaScript

复制代码
proxy: {
  '/': { // 匹配所有路径
    target: baseUrl,
    changeOrigin: true
  }
}

灾难发生了: 当你刷新页面想看网页时,浏览器请求 index.html

  1. Vite 拦截到 /index.html

  2. 发现符合 / 的匹配规则。

  3. 强行转发:它把请求发给了 Java 后端。

  4. 后端报错 :Java 大厨一看,"我要的是 ID,你给我个 index.html 干啥?"

结果就是:你的网页打不开了,因为所有的静态文件请求都被当成接口转发走了。


3. 深度分析:为什么要 Rewrite 而不直接让后端支持 /api?

你可能会问:"那我不重写,我让 Java 接口也叫 /api/getsingelUser 不就行了?"

当然可以!如果你这样做,配置就变成了:

JavaScript

复制代码
proxy: {
  '/api': {
    target: baseUrl,
    changeOrigin: true
    // 不需要 rewrite 了!
  }
}

这种做法在很多公司也非常流行。 但为什么要 rewrite 的方案更常见呢?

  1. 后端独立性 :后端接口可能已经写好了(比如就是 /test),为了配合前端的跨域需求去改所有后端的代码,代价太大。

  2. 环境统一 :有时候你本地开发需要 /api 做区分,但上线后的真实域名(比如 api.zhurenjin.com)本身就代表了接口,不需要路径前缀。通过 rewrite,你可以让前端代码保持逻辑一致。

nginx

既然你理解了 Vite 的"红袖标"原理,那 Nginx 的 location /api/ 就非常好懂了。它在生产环境(线上服务器)扮演的角色,和 Vite 在开发环境扮演的角色一模一样

但是,Nginx 的语法有一个非常微妙的"陷阱",决定了它是否会自动帮你把 /api 删掉。


1. Nginx 转发的两种写法(最核心的区别)

假设你前端请求的地址是:http://你的服务器IP/api/getsingelUser/1

方案 A:自动删掉 /api(对应 Vite 的 rewrite)

如果你希望转发给 Java 的路径是 /getsingelUser/1,你需要在 proxy_pass 的 IP 地址后面加一个斜杠 /

Nginx

复制代码
location /api/ {
    # 注意:IP 端口后面有斜杠!
    proxy_pass http://120.xx.xx.xx:8080/; 
}
  • 逻辑 :Nginx 发现你请求里匹配了 /api/。因为它看到 proxy_pass 后面带了路径(哪怕只是一个 /),它就会把请求中匹配 location 的那部分(/api/替换proxy_pass 后面的路径(/)。

  • 结果/api/getsingelUser/1 \\rightarrow [http://120.xx.xx.xx:8080/getsingelUser/1](http://120.xx.xx.xx:8080/getsingelUser/1)

方案 B:保留 /api(原封不动转发)

如果你希望转发给 Java 的路径依然带着 /api,那么 proxy_pass 的 IP 后面不要加任何东西

Nginx

复制代码
location /api/ {
    # 注意:IP 端口后面没有斜杠!
    proxy_pass http://120.xx.xx.xx:8080; 
}
  • 逻辑:Nginx 认为这只是一个纯粹的代理,它会把整个原始路径直接拼在后面。

  • 结果/api/getsingelUser/1 \\rightarrow [http://120.xx.xx.xx:8080/api/getsingelUser/1](http://120.xx.xx.xx:8080/api/getsingelUser/1)


2. 为什么我们要配置 Nginx 代理线上 IP?

当你的前端页面(HTML/JS)部署在 Nginx 上时,浏览器认为这个页面的"家"在 http://你的服务器IP

  1. 避开跨域限制 :浏览器允许网页请求自己"家"里的资源。所以你请求 /api/xxx 是合法的(同源)。

  2. 隐藏真实端口 :你的 Java 可能开在 80809000。如果你直接让前端访问这些端口,你得在云服务器后台开一堆防火墙端口,很不安全。

  3. 统一入口 :通过 Nginx,你只需要对外开放一个 80 端口。所有的前端网页、后端接口、甚至图片资源,全部通过这一个大门进出。


3. 最佳实践:我该怎么配置?

既然你本地 Vite 配置了 rewrite,说明你的 Java 代码里 @GetMapping不带 /api 的。为了保持一致,线上 Nginx 建议这样配置:

Nginx

复制代码
server {
    listen       80;
    server_name  你的域名或公网IP;

    # 1. 前端静态页面
    location / {
        root   /usr/share/nginx/html/dist; # 你前端打包放的位置
        index  index.html;
        try_files $uri $uri/ /index.html;
    }

    # 2. 后端接口代理
    location /api/ {
        # 加上这个斜杠,效果等于 Vite 的 rewrite
        proxy_pass http://你的Java服务器内部IP:8080/; 
        
        # 标准配置:把真实的客户端信息传给 Java
        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;
    }
}

💡 总结下:

  • Vite 代理 :靠 rewrite 正则表达式手动删掉 /api

  • Nginx 代理 :靠 proxy_pass 结尾的那个斜杠 / 自动替换掉 /api

一句话: 只要你发现线上报 404,先去检查 Nginx 配置里 proxy_pass 那个 IP 后面有没有漏掉斜杠!

相关推荐
之歆2 小时前
Vue Router 深度解析 — 从浏览器导航模型到 SPA 路由工程
前端·javascript·vue.js
guojb8242 小时前
Vue3 高阶技巧:使用 AST 将 HTML 字符串优雅渲染为自定义组件
前端·javascript·vue.js
之歆2 小时前
API 层架构设计 — 从 RESTful 到 GraphQL 的范式演进
vue.js·后端·restful·graphql
蜡台2 小时前
Vue3 props ref router 数据通讯传输等使用记录
前端·javascript·vue.js·vue3·router·ref
mfxcyh3 小时前
实现签名画板
前端·javascript·vue.js
cd ~/Homestead3 小时前
Vue 配置跨域的两种方法
前端·javascript·vue.js
i220818 Faiz Ul3 小时前
教育资源共享平台|基于springboot + vue教育资源共享平台系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·教育资源共享平台
happymaker06263 小时前
Vue自定义指令、插槽、路由的简单使用
前端·javascript·vue.js
Reisentyan3 小时前
[vue3]HTML Learn Data Day 9
前端·vue.js·html