浏览器缓存
浏览器缓存
1.前言
浏览器缓存就是将用户请求的静态资源,HTML、CSS、JS、Img 等存储在电脑磁盘或者内存中,下次请求时,直接读取缓存中的数据,不需要再从服务器拉取。
- 优点:
- 减少冗余数据的传输,节省了带宽
- 减少了服务器负担
- 提升了网页的加载速度
- 缺点:
- 使用不当时,服务器的代码和客户端页面不一致,不同步
2.缓存流程
浏览器第一次请求资源,并缓存资源
3.缓存规则
强缓存和协商缓存
强缓存
资源没有过期,取缓存,否则,请求服务器资源
资源是否过期这个规则,是第一次请求服务器时,返回值中,Response Header(响应头)中的 Cache-Control 决定的
Cache-Control 的值主要有以下:
max-age=31536000 (重要)过期时间,在31536000秒内是直接读取缓存,不需要向服务器发起请求
no-cache (重要)不进行强缓存
no-store 不进行强缓存,也不进行协商缓存
private 仅浏览器缓存
public 浏览器和代理服务器都可以缓存
强缓存流程:
结论:
强缓存规则,如果 Cache-Control 设置了 max-age=xxxxxx秒,命中强缓存,则读取磁盘缓存
如果max-age=xxx秒过期了,或者设置了no-cache,走协商缓存
协商缓存
触发条件:
- Cache-Control 的值为 no-cache
- max-age 过期了
etag: 每个文件都有一个 etag,文件改动后,etag 就会改变
Last-Modified: 文件的最后修改时间
每次请求服务器资源,Response Header 中就会有 etag 和 Last-Modified,在下一次请求中,Request Header 中会带着 etag 和 Last-Modified,(字段名变了:ETag-->If-None-Match,Last-Modified-->If-Modified-Since),服务器根据传递过来的标识,资源目前的标识,进行比对,判断资源是否改动
协商缓存流程
结论:
- 请求服务器资源时,将 etag 和 Last-Modified 传递给服务器,服务器和最新资源对比
- 资源改动了,返回最新资源,状态码 200
- 资源没有改动,从本地读取缓存,状态码 304
注意: 协商缓存,需要向服务器发起请求,由服务器来判断是读取本地缓存还是返回最新资源。资源没有更改时,返回的 Header 信息,所以占用带宽相对小;资源有改动时,还需要返回body,所有占用带宽相对大。
配置缓存规则
nginx 配置:
服务端代码中配置:
`
response.setHeader('Cache-Control', 'no-cache')
response.setHeader('Pragma', 'no-cache')
response.setDateHeader('Expires', 0)
`
总结与思考
-
有 Last-Modified,为什么还要 etag
- 文件内容没有改变,只是修改时间变化了,这时候还是希望读取缓存
- 文件修改非常频繁,比如1s内修改了n次,Last-Modified 只能精确到秒,所以无法判断该文件修改
-
强缓存和协商缓存对比
缓存类型 获取资源 状态码 发送请求到服务器 强缓存 从磁盘获取 200 否,直接读取缓存 协商缓存 从内存获取 304 是,通过服务器来决定 -
用户行为对缓存的影响
用户操作 Cache-Control etag/Last-Modified 地址栏回车 有效 有效 页面链接跳转 有效 有效 打开新窗口 有效 有效 前进后退 有效 有效 F5 刷新 无效 有效 Ctrl + F5 刷新 无效 无效 注意: F5 会跳过强缓存,直接走协商缓存;Ctrl + F5 跳过所有缓存规则,重新获取服务器资源
-
项目缓存策略
react 和 vue 单页面应用,应用打包的时候,文件名做了 hash 处理了,所以每次打包的产物都是不同的,所以 js css img 都不需要我们操作了
index.html,我们需要在 nginx 做一个 no-store或者 no-cache,保证每次请求的 html 都是最新的,因为 html 中引入 js css img等静态资源,如果 html 走强缓存,引入的 js css img 等静态资源是不是有可能就是之前的静态资源呢?