不管三七二十一,先丢一张流程图,然后看个一分钟。
有了大致的流程印象之后,我就来补充说明一下大概流程:
PS:面试的时候可以按大概流程来说。
当我们进入页面或刷新页面时,浏览器会加载资源。
此时,浏览器会检查是否有强缓存,即判断是否有expires或者cache-control(cache-control优先级更高)。
如果有,则查看是否过期,未过期则从缓存读取资源进行加载。
如果过期,则判断浏览器是否有协商缓存。协商缓存标志包括了Last-Modify/If-Modify-Since和ETag/If-None-Match(ETag优先级更高)。
如果没有,则直接向服务器发送请求获取资源。
如果有,则向服务器发送协商缓存标志,服务器根据浏览器发送过来的标志判断是否与服务器上相同。
若相同,则服务器返回 304,并且不会返回资源内容,浏览器从协商缓存读取资源进行加载。
若不同,则服务器返回200,并返回资源内容给浏览器加载。
讲完了大概流程,就需要来补充细节啦。
浏览器缓存分为强缓存和协商缓存
强缓存
强缓存分为memory cache和disk cache,如下表所示。
memory cache | disk cache | |
---|---|---|
定义 | 即内存缓存,将资源缓存在内存中 | 即磁盘缓存,将资源缓存在磁盘中 |
相同点 | 能存放JS,CSS,图片等内容 | 能存放JS,CSS,图片等内容 |
不同点 | 退出进程时数据会被清除 | 退出进程时数据不会被清除 |
三级缓存原理
浏览器先在内存中查找资源,如果有,直接加载。
如果内存中不存在,则在磁盘中查找,如果有直接加载。
如果磁盘中也没有,那么就进行网络请求。
请求获取的资源缓存到硬盘和内存。
协商缓存
当强缓存没有命中的时候,浏览器会发送一个请求到服务器,服务器根据 header 中的部分信息来判断是否命中协商缓存。
协商缓存标志分为Last-Modify/If-Modify-Since和ETag/If-None-Match。
Last-Modify/If-Modify-Since
浏览器第一次请求一个资源的时候,服务器返回的 header 中会加上 Last-Modify,Last-modify 是一个时间标识该资源的最后修改时间。
当浏览器再次请求该资源时,request 的请求头中会包含 If-Modify-Since,该值为缓存之前返回的 Last-Modify。服务器收到 If-Modify-Since 后,根据资源的最后修改时间判断是否命中缓存。
如果命中缓存,则返回 304,并且不会返回资源内容,并且不会返回 Last-Modify。
缺点:
短时间内资源发生了改变,Last-Modified 并不会发生变化。
周期性变化。如果这个资源在一个周期内修改回原来的样子了,我们认为是可以使用缓存的,但是 Last-Modified 可不这样认为,因此便有了 ETag。
ETag/If-None-Match
与 Last-Modify/If-Modify-Since 不同的是,Etag/If-None-Match 返回的是一个校验码。ETag 可以保证每一个资源是唯一的,资源变化都会导致 ETag 变化。服务器根据浏览器上送的 If-None-Match 值来判断是否命中缓存。
与 Last-Modified 不一样的是,当服务器返回 304 Not Modified 的响应时,由于 ETag 重新生成过,response header 中还会把这个 ETag 返回,即使这个 ETag 跟之前的没有变化。
Last-Modified 与 ETag 是可以一起使用的,服务器会优先验证 ETag,一致的情况下,才会继续比对 Last-Modified,最后才决定是否返回 304。
部分内容引用自《实践这一次,彻底搞懂浏览器缓存机制》:https://segmentfault.com/a/11...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。