Nginx实现静态资源永久缓存的关键是服务构建时已带内容哈希的文件,并配置immutable缓存头;需前端工具生成contenthash文件名,Nginx按后缀匹配设置expires 1y和Cache-Control "public, immutable",HTML禁用强缓存。

在 Nginx 中实现静态资源“永久缓存”,关键不在 Nginx 本身生成哈希,而在于让 Nginx 正确服务那些**构建时已带内容哈希的文件**,并配合精准缓存头,使浏览器真正信任该 URL、长期不请求验证。URL 哈希必须由前端构建工具(如 Webpack、Vite、Rollup)注入,Nginx 只负责识别、响应和缓存策略落地。
构建阶段生成带哈希的文件名
这是整个机制的前提。不能靠 Nginx 动态加参数(如 ?v=123),也不能手动改名——必须基于文件内容生成唯一哈希,确保内容变则 URL 变。
- Webpack:用
[contenthash]替代[hash],例如main.[contenthash:8].js - Vite:默认启用
build.rollupOptions.output.entryFileNames和assetFileNames的哈希占位符,如assets/index.[hash].js - 输出示例:
/static/js/app.e8f3a2d4.js、/static/css/base.b5c7d9e1.css - HTML 中的引用也需同步更新(由构建工具自动完成),例如:
<script src="/static/js/app.e8f3a2d4.js"></script>
Nginx 按扩展名匹配并启用 immutable 长期缓存
Nginx 不需要识别具体哈希值,只需通过正则匹配常见静态资源后缀,并统一设置强缓存策略。重点是 immutable —— 它告诉浏览器:“这个 URL 对应的资源,在过期前绝不会变更”,从而跳过 If-None-Match 等协商请求,真正实现零验证加载。
配置示例:
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2|ttf|webp|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}-
expires 1y提供明确的过期时间(等效于max-age=31536000) -
immutable是现代浏览器支持的关键指令,Chrome 49+、Firefox 49+、Safari 11.1+ 均支持 - 匹配的是文件后缀,不是路径是否含哈希——只要文件名带哈希且内容不变,该策略就安全有效
避免未哈希路径干扰缓存节奏
如果存在不带哈希的通用路径(如 /static/ 根目录或 /favicon.ico),它们无法享受长期缓存,反而可能因缓存过久导致 HTML 引用失效后降级失败。
- 对无指纹资源单独限制缓存时长:
location /static/ { expires 1m; add_header Cache-Control "no-cache, must-revalidate"; } - 入口 HTML 文件必须禁用强缓存:
location ~* \.html$ { add_header Cache-Control "no-cache, must-revalidate"; },确保用户每次访问都能拿到最新引用关系 - Next.js 用户可直接匹配
/_next/static/路径,它天然带哈希,适合开 1 年 + immutable
验证与生效要点
配置写完不等于生效,需主动验证浏览器实际收到的响应头,并确认 Nginx 已重载。
- 执行
nginx -t && nginx -s reload确保配置热生效 - 用浏览器开发者工具检查资源响应头:
Cache-Control: public, immutable和Expires是否存在且合理 - 首次加载后关闭网络,刷新页面——带哈希的 JS/CSS 应仍能执行;修改代码重新构建后,新哈希文件会触发全新请求,旧缓存自然被绕过
- 注意 CDN 或中间代理是否透传
immutable;若不支持,至少保留public, max-age=31536000


















