nginx静态资源缓存分客户端(浏览器)和服务端(磁盘)两层:浏览器端用add_header cache-control控制,如public,max-age=31536000,immutable;服务端用proxy_cache配合内部location实现磁盘缓存,并需sendfile等优化文件读取。

在 Nginx 中设置静态资源缓存,核心是分两层控制:**客户端(浏览器)缓存** 和 **服务端(Nginx 本地磁盘)缓存**。两者目标不同、配置方式不同,不能混用,也不该互相替代。
一、浏览器端缓存:靠 Cache-Control 和 expires 控制
这是最常用、最直接的缓存方式,让浏览器自己存 JS/CSS/图片等,避免重复请求。
-
优先用
add_header Cache-Control:比expires更灵活,能精确指定行为。例如:
add_header Cache-Control "public, max-age=31536000, immutable";
-
public允许 CDN 和中间代理缓存; -
max-age=31536000表示 1 年内不需重新请求; -
immutable告诉浏览器该资源不会变,连验证(如 If-None-Match)都跳过。
- 对 HTML 文件要谨慎:通常设为
no-cache或must-revalidate,避免用户看不到更新; - 带哈希名的资源(如
app.a1b2c3.js)可放心长期缓存;没哈希的 JS/CSS 建议设为max-age=86400(1 天)并配合版本号更新。
二、Nginx 服务端磁盘缓存:用 proxy_cache 模拟“本地代理”
这不是给浏览器用的,而是让 Nginx 把首次读取的静态文件存到磁盘,后续请求直接从磁盘发出去,减少对文件系统反复 open/read 的压力。
- 必须先在
http块定义缓存路径和共享内存区:
proxy_cache_path /var/cache/nginx/static_cache levels=1:2 keys_zone=static_cache:50m max_size=5g inactive=30d use_temp_path=off;
- 再在
location中启用它——但注意:Nginx 要求proxy_cache必须配合proxy_pass,不能直接和root或alias共用; - 推荐做法是用内部命名 location 实现伪代理:
location ^~ /static/ {<br> proxy_pass http://_internal_static_;<br> proxy_cache static_cache;<br> proxy_cache_valid 200 302 1h;<br> add_header X-Cache-Status $upstream_cache_status;<br>}
location @static_disk {<br> root /var/www/static;<br> try_files $uri =404;<br>}
- 这样既满足了 proxy_cache 的语法要求,又真正服务了本地文件;
-
inactive=30d表示 30 天没被访问就自动清理,适合静态资源; - 加
X-Cache-Status头方便调试是否命中缓存(HIT / MISS / BYPASS)。
三、按资源类型分流,避免规则冲突
location 匹配有优先级:^~ > 正则 ~* > 普通前缀。如果用了 location ^~ /static/,那下面所有正则规则(比如 location ~ \.js$)都不会生效。
- 正确做法是:把缓存策略写在匹配最具体的 location 里,例如:
location ^~ /static/js/ {<br> add_header Cache-Control "public, max-age=31536000, immutable";<br> root /var/www/static;<br>}
- 或者统一由一个
location ~* \.(js|css|png|jpg)$处理,但确保它不被更高优先级的^~或=覆盖; - HTML 文件建议单独处理,禁用强缓存:
add_header Cache-Control "no-cache, must-revalidate";
四、辅助优化:提升文件读取效率
缓存再好,底层文件读取慢也白搭。这几项配置能显著加快静态资源响应速度:
-
sendfile on;:启用内核零拷贝,大幅降低 CPU 开销; -
tcp_nopush on;:配合 sendfile,让 TCP 把数据包填满再发; -
open_file_cache max=10000 inactive=60s;:缓存文件句柄和元信息,减少 stat() 系统调用; -
aio on;和directio 4k;:对大文件启用异步 IO 和直接 IO,绕过页缓存,降低内存压力。











