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.productionVITE_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.jsexport 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.productionVITE_API_BASE_URL/api3. 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/infoNginx 配置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_URLhttp://127.0.0.1:8080这种配置本地看着能通打包后直接炸。生产环境尽量用相对路径VITE_API_BASE_URL/api然后通过 Nginx 转发。5. 排查时先看 Network不要一上来猜后端问题这次一开始差点让后端同事查半天日志。后来 Network 面板一看请求地址就不对问题基本就锁定在前端部署配置上了。前端 404 不一定都是前端代码问题也可能是 Nginx、base 路径、代理配置问题。排查顺序后面再遇到类似问题可以按这个顺序看打开浏览器 Network 面板看失败请求的真实地址确认本地请求地址和线上请求地址是否一致检查vite.config.js里的base配置检查.env.production里的接口前缀确认 Nginx 是否配置了接口转发检查proxy_pass末尾有没有/确认前端部署目录和访问路径是否一致最后这个问题不算复杂但挺典型。Vite 项目本地跑通只是第一步真正麻烦的是上线后各种路径、代理、环境变量对齐。尤其是从老项目迁移过来的时候原来可能用 Vue CLI、Webpack、Nginx 反向代理换到 Vite 之后配置方式变了但思路其实差不多。关键还是搞清楚本地请求是怎么走的打包后请求是怎么走的Nginx 到底转发了什么路径把这三条链路理清楚大部分 404 问题都能快速定位。