还是熟悉的图片
这篇我们来聚焦 App Cache
就像 我们手机的任何一款app都有缓存数据一样,浏览器也有,
浏览器优先检查应用缓存(App cache) 和HTTP缓存(强缓存如Cache-Control、弱缓存如ETag)。若缓存有效且未过期,直接从本地加载资源,跳过后续网络请求阶段。
在回答从输入url到页面展示,这个过程中做了什么 的时候,我们可能常常会忽略这个流程,但是它在我们前端性能优化层面却占有举足轻重的地位不是吗?
App cache
这里暂时空白,这里还是本人的盲区
HTTP缓存
HTTP缓存缓存不是浏览器本身能够完成的事情,因为在没有服务器端的其他信息的情况下,浏览器是无法判断资源的缓存是否过期的。其实,关于缓存的协商属于HTTP协议的一部分。HTTP协议中的一些Header和Status Code正是为了让客户端和服务器端缓存资源制定的。
强缓存
图1-1
1. Cache-Control: max-age(HTTP/1.1 标准)
- 机制:
服务器在响应头中声明资源有效期(秒),例如:Cache-Control: max-age=93312000 # 约 3 年(60*60*24*1080) - 浏览器行为:
- 在
max-age时间内,直接使用本地缓存(无网络请求)。 - DevTools 的
Network面板显示200 OK (from disk cache)。
- 在
2. Expires(HTTP/1.0 遗留)
- 机制:
指定资源的绝对过期时间(GMT 格式):Expires: Sat, 24 Aug 2019 09:03:00 GMT - 优先级:
当与Cache-Control共存时,max-age优先级更高。 - 为何同时存在?
兼容古老客户端(如 IE8-),但现代浏览器可忽略。
✅ 强缓存本质:浏览器仅依赖本地时钟判断缓存有效性,无需联系服务器
协商缓存
当强缓存过期时,浏览器发起**条件请求**,由服务器判断资源是否变更。
1. ETag + If-None-Match(精准校验)
- 流程:
- 首次请求 → 服务器返回资源并携带唯一标识符:
ETag: "abcd1234" # 通常为文件哈希值 - 缓存过期后 → 浏览器在请求头中附加该标识符:
If-None-Match: "abcd1234" - 服务器比对:
- 若 ETag 匹配 → 返回
304 Not Modified(空响应体,节省带宽)。 - 若 ETag 不匹配 → 返回
200 OK+ 新资源 + 新 ETag。
- 若 ETag 匹配 → 返回
- 首次请求 → 服务器返回资源并携带唯一标识符:
2. Last-Modified + If-Modified-Since(时间校验)
- 流程:
- 首次请求 → 服务器返回资源最后修改时间:
Last-Modified: Wed, 01 Jan 2020 13:30:00 GMT - 缓存过期后 → 浏览器在请求头中附加该时间:
If-Modified-Since: Wed, 01 Jan 2020 13:30:00 GMT - 服务器比对:
- 若未修改 → 返回
304 Not Modified。 - 若已修改 → 返回
200 OK+ 新资源 + 新Last-Modified。
- 若未修改 → 返回
- 首次请求 → 服务器返回资源最后修改时间:
3. 优先级与精度对比
| 策略 | 精度 | 缺陷 | 优先级 |
|---|---|---|---|
ETag 校验 | ⭐⭐⭐⭐⭐ 高 | 计算哈希消耗服务器资源 | 更高 |
Last-Modified 校验 | ⭐⭐ 中 | 最小单位为秒,1秒内修改无法检测 | 更低 |
缓存策略设计最佳实践
1. 静态资源(JS/CSS/图片)
# 强缓存:内容哈希命名文件确保永不失效
Cache-Control: public, max-age=31536000, immutable
- 原理:
main.abcd1234.js文件名含哈希 → 内容变更则 URL 变 → 强缓存安全。
2. 动态内容(API 响应或者index.html)
# 协商缓存:每次请求需验证
Cache-Control: no-cache
ETag: "xyz789"
- 效果:
避免返回过时数据,同时减少未变更资源的传输量。
总结:
既然App Cache 可以跳过后面网络请求,自然可以优化首屏性能,我们可以根据上文提到的缓存策略
优化非首次加载页面的性能,这部分其实只需要打包工具简单配置+服务器的响应头配合即可,是很划算的性能优化手段