immutable声明资源在max-age有效期内内容绝不变,浏览器刷新时也跳过If-None-Match等条件请求,直接复用缓存;必须与max-age共用且资源URL需含内容哈希才生效。

Cache-Control 的 immutable 属性本身并不表示“永不改变”,而是声明:**在 max-age 指定的有效期内,该资源内容绝不会变更**。浏览器据此跳过所有条件请求(如带 If-None-Match 或 If-Modified-Since 的请求),哪怕用户手动刷新页面,也直接复用本地缓存,不发任何验证请求。
它依赖两个前提才能生效
immutable 不是独立指令,必须与 max-age 配合使用,且资源本身需满足不可变语义:
-
必须显式设置 max-age:例如
Cache-Control: max-age=31536000, immutable。单独写immutable无效,浏览器会忽略。 -
资源 URL 必须唯一对应固定内容:典型做法是文件名嵌入内容哈希(如
main.a1b2c3d4.js)。一旦内容变化,URL 改变,旧缓存自然失效,新请求走全新路径 —— 这才是 immutable 可靠运行的基础。
它如何阻止协商请求
当浏览器发现响应头含 max-age=31536000, immutable,且当前缓存未过期时:
- 即使用户按 F5 刷新、或 Ctrl+R 重载,也不附加 If-None-Match / If-Modified-Since 请求头;
- 不再等待服务器返回 304,彻底绕过协商缓存流程;
- 直接从磁盘/内存加载资源,Network 面板显示
200 (from memory cache)或200 (from disk cache)。
配套配置不能遗漏
要让 immutable 发挥全部效果,服务端还需同步关闭干扰性机制:
-
禁用 ETag 和 Last-Modified:Nginx 中可加
etag off;和if_modified_since off;,避免浏览器生成条件请求头; - 按扩展名精准匹配规则:只对 .js、.css、.png 等静态资源设置 immutable,HTML 或 API 接口绝不适用;
- 避免与 no-cache/no-store 共存:二者语义冲突,会覆盖 immutable 行为。
支持情况与实际效果
Chrome 49+、Firefox 49+、Safari 11.1+、Edge 79+ 均支持 immutable。实测中,启用后可消除约 20% 的冗余 304 请求(Facebook 早期数据),尤其在高频刷新场景下降低源站压力明显。但它不是魔法开关——若资源未做哈希命名,或 max-age 设置过短,immutable 就失去意义。


















