前言
作为前端开发者,你一定遇到过这样的场景:刷新页面时,图片、CSS、JS 文件瞬间加载完成,浏览器控制台显示200 OK (from disk cache);也可能见过304 Not Modified的响应状态码。这些背后,都是浏览器缓存在发挥作用。
浏览器缓存是前端性能优化的核心手段之一,它通过将已请求的资源保存在本地,避免重复的网络请求,既能大幅提升页面加载速度,减少用户等待时间,又能降低服务器压力和带宽消耗,本文将从缓存分类,核心原理,实际配置,实战技巧四个维度,把浏览器缓存讲透
一. 浏览器缓存的整体分类
从缓存的触发逻辑和与服务器的交互方式来看,浏览器缓存主要分为两大类型,优先级从高到低依次为: 强缓存 和协商缓存
整个缓存的判断流程可以概括为:
-
浏览器发起请求时,首先判断本地是否有该资源的缓存,且是否符合强缓存规则;
-
若强缓存生效,直接使用本地缓存,不与服务器产生任何交互,返回
200 OK (from disk cache/memory cache); -
若强缓存失效(缓存过期或规则不允许), 则发起请求到服务器,通过协商缓存规则判断资源是否更新;
-
若协商缓存判定资源未更新,服务器返回
304 Not Modified,浏览器使用本地缓存;若资源已更新,服务器返回200 OK+ 新资源,浏览器更新本地缓存并使用。
简单来说: 强缓存是浏览器自己说了算,协商缓存时浏览器问服务器,服务器说了算
二. 强缓存: 无交互的极速缓存
强缓存是浏览器缓存中效率最高的一种,因为它完全不需要和服务器通信,直接从本地读取资源,是前端性能优化的首选方案
1. 核心控制头
强缓存的规则主要通过HTTP 响应头 中的两个字段控制,其中Cache-Control是现代浏览器的主流选择,Expires是为了兼容老浏览器的备用方案。
(1)Cache-Control(推荐使用)
Cache-Control是 HTTP/1.1 中定义的字段,支持多值组合,核心值为max-age,也是我们最常用的配置,格式为
Cache-Control: public, max-age=31536000
max-age:单位为秒 ,表示资源的缓存有效期。31536000秒 = 365 天,代表该资源 1 年内为有效缓存;public:表示该资源允许浏览器、CDN、代理服务器等所有中间节点缓存,适合静态资源;private:默认值,表示仅允许浏览器缓存,代理服务器 / CDN 不缓存,适合用户相关的动态资源;no-cache:注意不是 "不缓存",而是跳过强缓存,直接走协商缓存;no-store:完全不缓存,每次请求都必须从服务器重新下载,适合实时性要求极高的资源(如支付结果、验证码)
(2)Expires(兼容老浏览器)
Expires是 HTTP/1.0 中定义的字段,值为绝对时间戳(GMT 格式)
Expires: Wed, 21 Jan 2027 08:00:00 GMT
表示资源在该时间点前为有效缓存。但它有一个明显缺陷:依赖浏览器的本地时间 ,如果用户修改了本地时间,可能导致缓存判断失效。因此现代开发中,我们只需要配置Cache-Control,即可替代Expires。
2. 缓存的存储位置
强缓存的资源会被浏览器存放在两个位置,控制台会明确标识:
- from memory cache: 内存缓存,速度最快,资源存放在浏览器内存中,浏览器关闭后缓存失效,适合频繁使用的小资源(如常用的JS / CSS 片段);
- from disk cache: 磁盘缓存,速度稍慢但持久化,资源存放在本地硬盘中,浏览器关闭后仍存在,适合大部分静态资源(图片、大体积 JS/CSS、字体文件)。
浏览器会根据资源的大小,使用频率自动决定存储位置,开发者无需手动控制
3. 适用场景
强缓存适合发布后长期不变的静态资源,例如:
- 公司 logo、产品图片等静态图片
- 第三方库文件(如 Vue、React、jQuery 的压缩包)
- 字体文件、静态 CSS/JS 基础库
- 静态页面的静态资源(如 404 页面的图片)
三. 协商缓存: 按需更新的智能缓存
当强缓存失效后,浏览器会进入协商缓存流程。协商缓存的核心是与服务器交互,验证资源是否更新,若资源未更新,则避免重新下载资源体,仅返回状态码,从而减少网络传输量。
1.核心控制头
协商缓存通过两对 HTTP 头 配合实现,服务器在首次响应时设置资源标识 ,浏览器再次请求时携带该标识,服务器根据标识判断资源是否更新,两对字段可单独使用,也可搭配使用,其中ETag/If-None-Match的精度更高。
(1)Last-Modified + If-Modified-Since
这是基于资源最后修改时间的协商缓存方案,分为两步:
- 首次请求 :服务器返回资源时,在响应头设置
Last-Modified,值为资源的最后修改时间(GMT 格式)
Last-Modified: Tue, 20 Jan 2026 10:00:00 GMT
2 .再次请求 :浏览器携带If-Modified-Since请求头,值为上次保存的Last-Modified时间:
If-Modified-Since: Tue, 20 Jan 2026 10:00:00 GMT
3. 服务器判断:
- 若资源的最后修改时间晚于该值,说明资源已更新,返回200 OK + 新资源 + 新的Last - Modified;
- 若资源的最后修改时间等于 / 早于 该值,说明资源未更新,返回 304 Not Modified,无资源体
缺点: 精度低(仅能到秒级) , 若资源在1秒内多次修改,无法识别,若文件内容未变,仅修改了文件名/ 修改时间, 会被误判为资源更新
(2)ETag + If-None-Match
这是基于资源内容唯一标识的协商缓存方案,也是现代开发的首选,分为两步:
首次请求 :服务器根据资源的内容生成唯一哈希值 (如 MD5、SHA1),在响应头设置ETag,值为该哈希值:
ETag: "5d41402abc4b2a76b9719d911017c592"
浏览器保存该哈希值和对应的资源(资源内容不变,哈希值不变;内容修改,哈希值立即变化)。
再次请求: :浏览器携带If-None-Match请求头,值为上次保存的ETag哈希值:
If-None-Match: "5d41402abc4b2a76b9719d911017c592"
3. 服务器判断 :
- 若服务器重新计算的资源哈希值与请求头值不一致 ,说明资源已更新,返回
200 OK+ 新资源 + 新的ETag; - 若哈希值一致 ,说明资源未更新,返回
304 Not Modified。
优点: 精度极高,只要资源内容不变,无论修改时间如何,都能正确判定;缺点:服务器需要为每个资源计算哈希值,存在轻微的性能开销(但对于现代服务器,该开销可忽略)。
2. 适用场景
协商缓存适合可能会更新,但更新频率不高的资源,;例如:
- 项目的业务 CSS / JS 文件 (会随版本迭代更新) ;
- 动态页面的静态资源 (如文章详情页的配图)
- 后端接口返回的 JSON 数据 (如用户信息,商品列表)
四. 浏览器缓存的配置方式: 前端无权限,后端 / 服务器来实现
很多开发者会有疑问 : "这些 HTTP 头 该在哪里设置? 前端代码能写吗?"
核心结论 : 浏览器缓存的所有响应头(Cache-Control、Last-Modified、ETag),均由后端 / 服务器配置,前端几乎无法直接控制。因为 HTTP 响应头是服务器发给浏览器的 "指令",只有服务器有权力决定资源的缓存规则,前端只是 "遵守指令的一方"。
根据资源类型的不同,配置方式主要分为静态资源 和动态接口两种:
1. 静态资源:Web 服务器 / CDN 配置(推荐)
项目中的图片、CSS、JS、字体等静态资源,无需在后端业务代码中配置,直接在Web 服务器(Nginx/Apache) 或CDN上设置即可,这是工业级项目的标准做法。
2. 动态接口:后端业务代码配置
对于后端接口返回的 JSON 数据(如/api/user、/api/goods),需要在后端业务代码中手动设置缓存头,同时实现协商缓存的判断逻辑。
五. 总结
浏览器缓存是前端性能优化的基础且核心的手段,无需复杂的开发成本,只需合理配置,就能让页面加载速度得到质的提升
最后用一句话总结核心要点: 静态资源用强缓存,加哈希做版本控制; 动态资源用协商缓存,优先用ETag保证精度; HTML 禁用强缓存,作为资源更新的入口