ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Vite 项目打包后部分接口 404,本地跑得好好的,上线就炸,排查了大半天

Vite 项目打包后部分接口 404,本地跑得好好的,上线就炸,排查了大半天

最近一个后台项目从老架构迁到 Vite,本地开发一直没问题,接口请求、路由跳转、资源加载都正常。

结果打包丢到测试环境之后,页面能打开,但部分接口直接 404。

一开始以为是后端没部署,后来发现不是。后端接口都在,Postman 也能正常调通,只有前端打包后的请求路径不对。

最后定位下来,问题出在Vite 的base配置、Nginx 路由、以及接口代理环境差异这几个点没对齐。

下面把排查过程记一下,避免后面再踩同样的坑。


问题现象

本地开发环境:

pnpm dev

页面正常,接口请求路径也没问题,比如:

/api/user/info /api/order/list

打包之后部署到测试环境,访问地址变成了:

https://test.example.com/admin/

这时候页面能打开,但接口请求变成了:

https://test.example.com/api/user/info

后端实际接口路径是:

https://test.example.com/admin-api/user/info

所以前端请求直接 404。


第一反应:先看网络面板

打开浏览器 Network 面板,先看失败请求。

几个关键信息:

  • 请求状态:404
  • 请求地址:/api/user/info
  • 页面地址:/admin/
  • 后端真实接口前缀:/admin-api/

到这里基本可以确认,不是后端挂了,而是前端打包后的请求路径和后端实际路径没对上。


第二步:看 Vite 配置

项目里原来有个.env.production

VITE_API_BASE_URL=/api

接口封装里大概是这么用的:

const request = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL, timeout: 10000 })

本地开发没问题,是因为 Vite dev server 里配了代理:

server: { proxy: { '/api': { target: 'http://127.0.0.1:8080', changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, '') } } }

也就是说,本地请求/api/user/info,会被代理到:

http://127.0.0.1:8080/user/info

所以本地看起来没问题。

但打包之后,前端静态资源是直接由 Nginx 托管的,Vite 的 proxy 不会生效

这时候/api/user/info就会直接打到 Nginx,而 Nginx 没有对应的转发规则,自然 404。


第三步:发现 base 也有问题

排查完接口前缀后,又发现另一个问题。

测试环境访问地址是:

https://test.example.com/admin/

但打包后部分静态资源请求路径是:

/assets/index-xxx.js

而不是:

/admin/assets/index-xxx.js

这就会导致资源加载失败,页面白屏或者部分组件加载不出来。

原因是vite.config.js里没有配置base,默认是/

改成:

export default defineConfig({ base: '/admin/', plugins: [vue()], server: { proxy: { '/api': { target: 'http://127.0.0.1:8080', changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, '') } } } })

改完之后,静态资源路径就对了。


第四步:Nginx 配置没跟上

前端配置改完后,接口还是 404。

因为生产环境没有 Vite proxy,所以 Nginx 需要把/api转发到后端服务。

原来的 Nginx 配置大概是这样:

location / { root /data/web/admin; index index.html; try_files $uri $uri/ /index.html; }

这个配置只能处理前端路由和静态资源,不能处理接口转发。

后面补了一段:

location /api/ { proxy_pass http://127.0.0.1:8080/; 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_pass http://127.0.0.1:8080/;

末尾这个/很关键。

如果写成:

proxy_pass http://127.0.0.1:8080;

那请求/api/user/info转发到后端后,路径会变成:

/api/user/info

如果后端接口实际是:

/user/info

那还是会 404。

加上末尾/之后,/api/会被替换掉,转发路径变成:

/user/info

这个点很容易忽略。


最终改动

最后主要改了三个地方。

1.vite.config.js
export default defineConfig({ base: '/admin/', plugins: [vue()], server: { proxy: { '/api': { target: 'http://127.0.0.1:8080', changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, '') } } } })
2..env.production
VITE_API_BASE_URL=/api
3. Nginx 配置
server { listen 80; server_name test.example.com; location /admin { alias /data/web/admin; index index.html; try_files $uri $uri/ /admin/index.html; } location /api/ { proxy_pass http://127.0.0.1:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }

改完之后,重新打包部署,接口和资源都正常了。


问题原因总结

这次问题本质上是三个环境差异没对齐:

环境接口代理静态资源路径
本地 devVite proxy 生效/没问题
测试环境Nginx 转发需要/admin/
后端接口真实路径不同需要路径重写

本地开发时,Vite proxy 把很多路径问题掩盖了。打包上线后,proxy 没了,所有路径都得靠 Nginx 和前端配置自己处理,所以问题就暴露出来了。


几个容易踩的点

1. Vite proxy 只在开发环境生效

这个很关键。

很多人本地调试接口没问题,就觉得配置没问题,结果一打包就挂。

生产环境一定要单独处理接口转发,不能依赖 Vite proxy。

2.base配置要和部署路径一致

如果项目不是部署在根目录,而是类似:

https://test.example.com/admin/

base一定要配置成:

base: '/admin/'

不然静态资源路径会错。

3. Nginxproxy_pass末尾斜杠别乱删
proxy_pass http://127.0.0.1:8080/;

这个/会影响路径拼接。

如果前端请求:

/api/user/info

Nginx 配置:

location /api/ { proxy_pass http://127.0.0.1:8080/; }

转发后是:

/user/info

如果去掉末尾/

proxy_pass http://127.0.0.1:8080;

转发后是:

/api/user/info

这个差别很细,但排查起来很烦。

4. 前端环境变量不要写死本地地址

之前项目里有人直接在.env.production里写过:

VITE_API_BASE_URL=http://127.0.0.1:8080

这种配置本地看着能通,打包后直接炸。

生产环境尽量用相对路径:

VITE_API_BASE_URL=/api

然后通过 Nginx 转发。

5. 排查时先看 Network,不要一上来猜后端问题

这次一开始差点让后端同事查半天日志。

后来 Network 面板一看,请求地址就不对,问题基本就锁定在前端部署配置上了。

前端 404 不一定都是前端代码问题,也可能是 Nginx、base 路径、代理配置问题。


排查顺序

后面再遇到类似问题,可以按这个顺序看:

  1. 打开浏览器 Network 面板,看失败请求的真实地址
  2. 确认本地请求地址和线上请求地址是否一致
  3. 检查vite.config.js里的base配置
  4. 检查.env.production里的接口前缀
  5. 确认 Nginx 是否配置了接口转发
  6. 检查proxy_pass末尾有没有/
  7. 确认前端部署目录和访问路径是否一致

最后

这个问题不算复杂,但挺典型。

Vite 项目本地跑通只是第一步,真正麻烦的是上线后各种路径、代理、环境变量对齐。

尤其是从老项目迁移过来的时候,原来可能用 Vue CLI、Webpack、Nginx 反向代理,换到 Vite 之后,配置方式变了,但思路其实差不多。

关键还是搞清楚:

  • 本地请求是怎么走的
  • 打包后请求是怎么走的
  • Nginx 到底转发了什么路径

把这三条链路理清楚,大部分 404 问题都能快速定位。

返回列表