前端项目真上线了,Nginx 干的绝对不只是“把 dist 目录扔上去”。
很多人嘴上说前后端分离,真到发版的时候,还是一把梭:npm run build,把静态文件丢服务器,完事。结果第二天就开始见鬼了:刷新 404、接口跨域、静态资源缓存不生效、用户明明已经更新了页面还在跑旧代码。 这时候你再看 Nginx,就不会把它当个“文件托管工具”了,它其实是前端上线之后的第一道现场处理层。
我一般看一个前端项目配没配明白,先不看 React、Vue 写得多花,先看 Nginx。
先说最表面的那个活:托管静态资源。
server {
listen 80;
server_name demo.example.com;
root /data/www/app;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
这段配置很多人都见过,但不少人只是照抄,不知道为啥非得 try_files。 单页应用最常见的坑就在这。你本地开发时走的是 dev server,路由切换靠前端接管;上线后用户直接访问 /user/order/1024,Nginx 会去磁盘找这个路径对应的文件,找不到就 404。 所以这里不是“优雅配置”,是不给 index.html 兜底你就等着被问。
第二个活,反向代理接口。
这个更常见,但也更容易配得半懂不懂。前端本地开发时,最烦的不是页面,是跨域。上线之后也一样。浏览器认域名、认端口、认协议,不认你“这俩服务其实是一家的”。
server {
listen 80;
server_name demo.example.com;
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;
}
location / {
root /data/www/app;
index index.html;
try_files $uri $uri/ /index.html;
}
}
前端调用 /api/user/profile,Nginx 给你转到后端服务。 这样浏览器眼里,请求还是发给同一个域名,跨域问题直接绕过去。很多场景下,这比你在后端到处开 CORS 省事得多。尤其项目一多,测试、预发、生产三套环境一起跑,Nginx 比前端代码里写死一堆 baseURL 靠谱。
再往后,就是缓存。
这块我见过太多“以为开了 gzip 就算优化过”的。实际上前端上线后最容易出事的,不是页面打不开,而是用户打开的是旧页面,新接口、新字段、新 bundle 对不上,白屏。
静态资源和 index.html 的缓存策略,必须分开。
location / {
root /data/www/app;
index index.html;
try_files $uri $uri/ /index.html;
add_header Cache-Control "no-cache";
}
location /assets/ {
root /data/www/app;
expires 30d;
add_header Cache-Control "public, max-age=2592000, immutable";
}
index.html 一般不敢让它长时间缓存,因为它里面引用的是最新的 js、css 文件。 真正该狠狠干缓存的是带 hash 的静态资源,比如:
console.log('app loaded');
// 构建后可能变成 app.a8f3c91d.js
文件名都带指纹了,你就放心让浏览器缓存。文件内容一变,hash 也变,用户自然会拉新文件。 这地方很多线上“怎么我改了代码用户没生效”的问题,不是前端框架的锅,是 Nginx 缓存策略配反了。
再一个,压缩。
这事很小,但真能省流量、提首屏,尤其前端包没收住的时候,Nginx 至少还能帮你兜一层。
gzip on;
gzip_min_length 1k;
gzip_comp_level 5;
gzip_types
text/plain
text/css
application/javascript
application/json
application/xml
image/svg+xml;
别一上来就把压缩级别拉满。CPU 不是不要钱。 线上的取舍一般不是“压得最狠”,而是“压缩收益和机器开销别打架”。这点跟前端打包优化一个路子,别老想着极限参数,先看现场瓶颈在哪。
还有个很实用但经常被忽略的活:环境隔离。
很多前端项目嘴上说多环境,最后还是靠手改配置文件。真出一次“测试环境接口打到生产库”,人就老实了。 Nginx 这里能把不同域名、不同路径直接分开,不让前端包自己背全部环境判断。
server {
listen 80;
server_name test.demo.example.com;
location /api/ {
proxy_pass http://10.10.1.23:8080/;
}
}
server {
listen 80;
server_name demo.example.com;
location /api/ {
proxy_pass http://10.10.8.16:8080/;
}
}
前端同一套代码,发到不同环境,流量走不同后端。 这种事你让前端工程配置全扛,不是不行,但后面排障会很烦。特别是接口路径一致、只是上游地址不同的时候,放在 Nginx 这层更顺手。
再说一个上线后很关键的用途:灰度和切流。
前端不是只有“全量发布”这一种死法。你页面一改大,最好别一把全放。Nginx 能按路径、按 Cookie、按请求头,甚至按用户分流到不同版本。
location / {
if ($http_cookie ~* "betaUser=true") {
root /data/www/app-beta;
}
root /data/www/app;
try_files $uri $uri/ /index.html;
}
这配置未必是最终最优写法,但意思很直白: 你完全可以让一部分用户先吃新包,出问题也不至于全站一起陪葬。前端发版能不能稳,有时候不在代码,在发布手法。
最后还有个作用,日志。
前端页面出问题,第一反应别老盯着浏览器控制台。线上有没有大量 404、某个资源是不是持续 5xx、某个接口是不是被刷爆,Nginx access log 一翻,很多事比你在群里问“大家能打开吗”快得多。
log_format main '$remote_addr - $time_local "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $request_time';
access_log /var/log/nginx/access.log main;
有些前端问题,看着像代码 bug,实际上是资源路径错了; 有些看着像后端超时,实际上是代理层转发就没配对; 有些看着像用户网络差,结果日志一拉,全是某个 chunk 文件 404。
所以前端到底用 Nginx 做啥?
说简单点,它当然能托管页面。 但真到生产环境,它更像前端项目的门卫、转发员、缓存控制器、压缩器、灰度开关和第一现场记录仪。前端代码决定“功能是什么”,Nginx 决定“这个东西上线后像不像能活”。
很多团队前端工程化做得很热闹,Vite、Webpack、CI、自动发版一套不少,结果 Nginx 配置还是两年前抄的。那不叫上线,那叫碰运气。
该文章在 2026/5/26 18:24:44 编辑过