[toc]
| 单词 | 词性 | 音标 | 含义 |
|---|---|---|---|
| static | adj. | /ˈstætɪk/ | 静态的(图片、CSS、JS 等不变资源) |
| dynamic | adj. | /daɪˈnæmɪk/ | 动态的(需要后端实时生成的请求) |
| location | n. | /ləʊˈkeɪʃn/ | 匹配规则(按路径/类型区分请求去向) |
| root | n. | /ruːt/ | 根目录(静态文件的磁盘位置) |
| try_files | n. | /traɪ faɪlz/ | 依次尝试文件(找不到回退到 index.html) |
Lecture05-Nginx-动静分离配置
1、本节讲什么
把静态资源(图片、CSS、JS)交给 Nginx 直接返回(快、不占后端),把动态请求(/api)转发给后端。这就是动静分离,也是前后端分离项目最常见的 Nginx 配置。
2、概念速览
什么是动静分离:请求来了先分一分——静态的 Nginx 自己给,动态的转后端。
请求 ─→ Nginx ─┬─ 静态资源(.js/.css/图片) → Nginx 直接从磁盘返回(不走后端)
└─ 动态请求(/api) → 转发给后端服务器
类比(Java):像"CDN / 静态资源服务器 + 应用服务器"分工——静态不进 Tomcat/SpringBoot,动态才进,后端压力小很多。
关键:靠 location 按路径/文件类型区分。静态用 root/alias 指到磁盘目录,动态用 proxy_pass 转后端。
3、照着做
① 准备静态目录(放前端打包产物,如 dist)
sudo mkdir -p /var/www/flower-front
# 把前端构建产物(npm run build 后的 dist 内容)拷进去
sudo cp -r /path/to/dist/* /var/www/flower-front/
② 在站点配置里写动静分离
server {
listen 80;
# —— 静态:前端页面 + 资源,Nginx 直接返回 ——
location / {
root /var/www/flower-front; # 静态文件根目录
index index.html;
try_files $uri $uri/ /index.html; # 前端路由刷新时回退到 index.html
}
# —— 动态:/api 开头的请求转后端 ——
location /api/ {
proxy_pass http://flower_backend; # 后端组(主题 4 配的)
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
}
}
说明:
proxy_pass http://flower_backend;(不带末尾/)会把/api/xxx原样转发给后端;若写成proxy_pass http://flower_backend;且后端接口是/api/xxx,路径就一致。具体以你后端接口前缀为准(可参考前端教程第 23/27 节的/api约定)。
关于 try_files:为什么前端 SPA 刷新要回退到 index.html
try_files $uri $uri/ /index.html; 是 Vue/React 单页应用(SPA)部署的灵魂配置,三个参数按顺序找文件:
| 顺序 | 参数 | 找什么 | 例子(请求 /logo.png) |
|---|---|---|---|
| ① | $uri | 找同名文件 | /var/www/flower-front/logo.png → 找到,直接返回 |
| ② | $uri/ | 找同名目录 | /var/www/flower-front/about/ 里的 index.html |
| ③ | /index.html | 前面都没找到,兜底返回这个 | 返回 SPA 入口 |
为什么需要第三个参数?
Vue/React 的路由是"假路由"——/user、/order、/about 这些路径都是前端 JS 用 History API 模拟的,服务器上根本不存在这些文件。
场景:用户在 /about 页面按 F5 刷新
没有 try_files:
浏览器 → Nginx:我要 /about
Nginx:磁盘上找 about 文件 → 不存在 → 404 ❌
有 try_files:
浏览器 → Nginx:我要 /about
Nginx:① 找 about 文件 → 没有
② 找 about/ 目录 → 没有
③ 兜底返回 /index.html
浏览器加载 index.html → Vue Router 读 URL 是 /about → Vue 自己执行路由操作 → 显示"关于我们" ✅
| 请求 | 磁盘上有没有 | 没有 try_files | 有 try_files |
|---|---|---|---|
/logo.png | 有 | 直接返回图片 | 直接返回(①命中) |
/css/app.css | 有 | 直接返回 | 直接返回(①命中) |
/about(SPA 路由) | 没有 | 404 | 返回 index.html,前端接管(③兜底) |
/order/123(SPA 路由) | 没有 | 404 | 返回 index.html,前端接管(③兜底) |
一句话:静态资源(js/css/png)真存在,直接返回;前端路由(/about、/order)假存在,兜底回 index.html 让前端路由去处理。
这就是为什么部署 Vue 项目到 Nginx 后,从首页点进子页面一切正常,但直接刷新子页面就 404——99% 就是漏了这行
try_files。
③ 测试并重载
sudo nginx -t
sudo systemctl reload nginx
④ 验证
curl http://localhost/ # 返回前端 index.html(静态)
curl http://localhost/assets/app.js # 返回静态 JS(Nginx 直接给,不转后端)
curl http://localhost/api/flowers # 返回后端数据(动态,转后端)
看 Nginx 日志能区分:静态请求由 worker 直接响应,动态请求走了后端。
4、常见疑问
-
Q:
root和alias有啥区别? A:root会把匹配的路径拼在 root 后面找文件(root /var/www; location /a/→ 找/var/www/a/x);alias是直接替换(alias /var/www/a; location /a/→ 找/var/www/a/x)。静态文件多用root,初学者先记住root就行。 -
Q:
/var/www这个目录对 Nginx 有什么特殊?必须放这吗? A:没有任何特殊性,Nginx 对目录位置零要求,root指到哪它读哪。用/var/www只是约定俗成——从 Apache 时代就这么放,Ubuntu 装完 Nginx 默认站点也在/var/www/html,大家跟着抄。实际放/opt/xxx、/data/xxx都行:误区 正解 Nginx 只认 /var/wwwNginx 对目录位置零要求, root指到哪读哪必须放 /var/www只是"大家都这么干",不是"Nginx 必须这么干" 只要满足两个条件:① 路径写对;② Nginx worker 进程(
www-data用户)对该目录有读权限。如果你非要放别处,给权限就行:sudo chown -R www-data:www-data /opt/flower-front真正"特殊"的不是目录,是权限——放
/var/www默认权限刚好允许www-data读,放自己家目录就会 403。 -
Q:前端是 Vue 单页应用,刷新
/flowers404 怎么办? A:就是上面那行try_files $uri $uri/ /index.html;解决的(详见上面"关于 try_files"展开说明)。 -
Q:图片请求也走后端怎么办? A:说明没命中静态
location。确认路径是否匹配location /(或专门的location ~* \.(png|jpg|js|css)$),并把文件放对root目录。
5、本节验证
- 理解动静分离的思想(静态自己给、动态转后端)✅
- 会配静态 root + try_files 与动态 proxy_pass ✅
- 会用 curl 分别验证静态与动态请求 ✅