动静分离核心是Nginx拦截静态请求自处理、转发动态请求给后端;location匹配顺序、root/alias路径配置、缓存头与gzip、响应头验证缺一不可,细节错误直接导致404/502。

直接说结论:动静分离不是“把文件挪个地方”就完事,核心是让 Nginx 拦截静态请求自己处理,把动态请求(如 .php、.jsp)原路转发给后端服务;配置错 location 顺序或 root 路径,80% 的 404 和 502 都由此而来。
location 匹配顺序决定谁处理请求
Nginx 不是按配置文件从上到下“执行”,而是先收集所有 location 块,再根据匹配规则选最优项。常见错误是把通用 location / 放在前面,结果所有请求(包括 /js/app.js)都被 proxy_pass 吞掉,根本没机会走到后面的静态规则。
- 必须把静态资源的正则匹配写在动态代理之前,例如:
location ~ \.(js|css|png|jpg|gif|ico)$ - 优先级高于
location /的是location = /xxx(精确匹配)和location ^~ /static/(前缀匹配不继续正则) - 避免用
location /包裹整个 proxy_pass,改用更窄的路径,比如location /api/或location ~ \.(php|jsp|do)$
root 与 alias 在静态路径中的区别
root 是拼接路径,alias 是替换路径——这个差一点,图片就全 404。
- 如果访问
http://example.com/img/logo.png,且配置为:location /img/ { root /data; },Nginx 实际查找的是/data/img/logo.png - 同样 URL,若改为:
location /img/ { alias /data/images/; },则查找的是/data/images/logo.png(注意结尾斜杠和不拼接/img/) - 用
root时,确保目录结构和 URL 路径严格对应;用alias更灵活,但必须带结尾/,否则会出错
动静分离后必须补上的缓存与头信息
只分开了请求,不加缓存和响应头,性能提升打五折。浏览器不会复用未声明过期时间的 JS/CSS,每次都要重请求。
- 在静态
location块里加上:expires 7d;(对不变资源)或expires epoch;(禁用缓存,用于开发) - 加上
add_header Cache-Control "public, immutable";可进一步提示浏览器长期缓存(适用于带哈希名的文件) - 别漏掉
gzip on;和gzip_types,否则文本类静态资源(JS/CSS/HTML)不压缩,白白多传几倍体积
验证动静是否真分离了
别只看页面能不能打开——要确认请求没走错路。最简单的方法是开浏览器开发者工具,看每个资源的 Response Headers:
- 静态资源(CSS/JS/IMG)应该有
Server: nginx,且没有X-Proxy-Upstream类字段 - 动态接口(
/api/login、/index.php)应该有Server: Apache或Server: nginx + Via: 1.1 localhost,说明被 proxy_pass 转发了 - 用
curl -I http://your.site/static/main.css直接看响应头,比点网页更快定位问题
最容易被忽略的是:静态文件物理路径没同步到 Nginx 所在服务器(尤其 Docker 或多机部署时),以及 location 中的正则漏写了转义点(比如写成 .js 而不是 \.js),导致匹配失效。这些细节不检查,配置写得再漂亮也没用。



















