聊聊浏览器缓存机制把
缓存可以说是性能优化中简单高效的一种优化方式了,它可以显著减少网络传输所带来的损耗。
对于一个数据请求来说,可以分为发起网络请求、后端处理、浏览器响应三个步骤。浏览器缓存可以帮助我们在第一和第三步骤中优化性能。比如说直接使用缓存而不发起请求,或者发起了请求但后端存储的数据和前端一致,那么就没有必要再将数据回传回来,这样就减少了响应数据。
接下来的内容中我们将通过以下几个部分来探讨浏览器缓存机制:
- 缓存位置
- 缓存策略
- 实际场景应用缓存策略
缓存位置
从缓存位置上来说分为四种,并且各自有优先级,当依次查找缓存且都没有命中的时候,才会去请求网络
- Service Worker
- Memory Cache
- Disk Cache
- Push Cache
- 网络请求
缓存策略
通常浏览器缓存策略分为两种:强缓存和协商缓存,并且缓存策略都是通过设置 HTTP Header
来实现的。
强缓存
强缓存可以通过设置两种 HTTP Header
实现:Expires
和 Cache-Control
。强缓存表示在缓存期间不需要请求,state code
为 200
。
这两区别就是 Expires
是 HTTP/1
的产物,设置具体的过期时间,到了指定时间需要再次请求。并且 Expires
受限于本地时间,如果修改了本地时间,可能会造成缓存失效。
而 Cache-Control
出现于 HTTP/1.1
,优先级高于 Expires
。该属性值表示资源会在多少秒后过期,需要再次请求。
协商缓存
如果缓存过期了,就需要发起请求验证资源是否有更新。协商缓存可以通过设置两种 HTTP Header
实现:Last-Modified
和 ETag
。并且 ETag
优先级比 Last-Modified
高。
当浏览器发起请求验证资源时,如果资源没有做改变,那么服务端就会返回 304 状态码,并且更新浏览器缓存有效期。
但是 Last-Modified
存在一些弊端:
如果本地打开缓存文件,即使没有对文件进行修改,但还是会造成 Last-Modified
被修改,服务端不能命中缓存导致发送相同的资源
因为 Last-Modified
只能以秒计时,如果在不可感知的时间内修改完成文件,那么服务端会认为资源还是命中了,不会返回正确的资源
因为以上这些弊端,所以在 HTTP / 1.1
出现了 ETag
。
以上就是缓存策略的所有内容了,看到这里,不知道你是否存在这样一个疑问。如果什么缓存策略都没设置,那么浏览器会怎么处理?
对于这种情况,浏览器会采用一个启发式的算法,通常会取响应头中的 Date 减去 Last-Modified 值的 10% 作为缓存时间。
多种指令配合流程图 常见指令作用实际场景应用缓存策略
频繁变动的资源
对于频繁变动的资源,首先需要使用 Cache-Control: no-cache
使浏览器每次都请求服务器,然后配合 ETag
或者 Last-Modified
来验证资源是否有效。这样的做法虽然不能节省请求数量,但是能显著减少响应数据大小。
代码文件
这里特指除了 HTML 外的代码文件,因为 HTML 文件一般不缓存或者缓存时间很短。
一般来说,现在都会使用工具来打包代码,那么我们就可以对文件名进行哈希处理,只有当代码修改后才会生成新的文件名。基于此,我们就可以给代码文件设置缓存有效期一年 Cache-Control: max-age=31536000
,这样只有当 HTML 文件中引入的文件名发生了改变才会去下载最新的代码文件,否则就一直使用缓存。