浏览器原理
缓存机制
为什么需要缓存?
- 更快获取资源,本地
- 减少服务器压力,重复资源
- 节省宽带,少请求
缓存分类
强缓存
直接使用本地资源,不会发起浏览器请求
通过两个http响应头实现:
- Expires,指定过期时间,已弃用。(可以通过故意改变系统时钟来引发问题)
- Cache-Control,指定经过时间,且优先级更高
案例:
HTTP/1.1 200 OK
Cache-Control: max-age=3600
max-age=3600
表示资源在 3600 秒(1 小时)内有效。- 在这 1 小时内,浏览器会直接从缓存加载资源,不会向服务器发送请求。
协商缓存
当强缓存失效时,浏览器会向服务器发起请求,服务器会根据请求头判断资源是否过期;
若资源未修改,服务器返回304,Not Modified,浏览器继续使用本地缓存;
若资源已修改,服务器返回新资源。
通过两组http头实现:
-
Last-Modified和If-Modified-Since
- 服务器返回Last-Modified,表示资源最后修改时间
- 浏览器下次请求时带上If-Modified-Since,浏览器根据时间判断资源是否更改
-
Etag和If-None-Match
- 服务器返回ETag,表示资源唯一标识
- 浏览器下次请求带上If-None-Match,浏览器根据标识判断
案例:
HTTP/1.1 200 OK
ETag: "123456"
- 服务器返回资源的唯一标识
ETag
。 - 浏览器下次请求时带上
If-None-Match: "123456"
。 - 如果资源未修改,服务器返回
304 Not Modified
,浏览器继续使用缓存。
工作流程
第一次请求
- 浏览器向服务器请求资源
- 服务器返回资源,并设置相关http头(如Cache-control、Etag)
- 浏览器将资源保存到缓存中
后续请求
-
浏览器检查强缓存是否有效
- 如果有效,直接从缓存加载资源
- 如果无效,向服务器发起请求,并携带上协商缓存相关的http头(如If-Modified-Since、If-None-Match)
-
服务器检查资源是否修改
- 如果未修改,返回304 Not-Modified,浏览器继续使用缓存
- 如果修改,返回新的资源,并更新缓存
最佳实践
静态资源使用强缓存
对于不经常变化的资源,如图片,css,js,可以设置较长缓存时间
Cache-Control: max-age=31536000
- 表示缓存,
max-age=31536000
表示缓存有效期为 1 年。 - 如果资源需要更新,可以通过修改文件名或添加版本号的方式强制浏览器重新加载。
如
<script src="app.v1.js"></script>
<!-- 更新后 -->
<script src="app.v2.js"></script>
动态资源使用协商缓存
对于经常变化的资源,如html、api数据,可以使用协商缓存
如
Cache-Control: no-cache
ETag: "123456"
no-cache
表示每次请求都需要验证缓存是否有效。- 服务器通过
ETag
或Last-Modified
判断资源是否修改。
禁用缓存
对于一些用户隐私相关的资源,可以完全禁用缓存,
如
Cache-Control: no-store
no-store
表示禁止浏览器缓存资源。