美文网首页大前端
浏览器缓存机制

浏览器缓存机制

作者: 柏丘君 | 来源:发表于2017-12-08 15:45 被阅读46次

    现代浏览器为了最大化的复用资源,减少网络请求,都提供了缓存机制。所谓缓存,就是在某次网络请求过程中保存的一份资源副本,在下一次对相同 URL 进行请求时,就可以从资源副本中读取内容,无需让服务器再发送一次。
    这里有一个简单的流程图,可供大家理解:


    缓存机制理解.png

    在这个图中,浏览器第一次向某个资源发起请求时,服务器会向浏览器发送该资源,当浏览器再次对该资源进行请求时,服务器向浏览器响应 304,浏览器收到 304 的响应后就知道这个资源应该从缓存中读取了。这就是浏览器缓存的一个大概流程。

    缓存类型

    缓存类型有两种:强缓存和协商缓存。具体采用哪种缓存是根据浏览器第一次请求资源时服务器返回的响应头来确定的。

    强缓存

    强缓存也叫本地缓存,或强缓。当某个资源应用了强缓存时,浏览器会将资源保存在本地,下一次再次请求时,无需向服务器发送请求,直接使用本地的缓存资源。
    浏览器在读取强缓存的资源时,可以选择从内存中读取(from memeory cache)或从硬盘中读取(from disk cache),具体采用哪种方式,由浏览器自行决定,不同的浏览器可能有差异。
    服务器返回下列的 HTTP 响应头便可让浏览器开启强缓存:
    1.Expires
    该响应头用来设置缓存资源的过期时间。这是 HTTP 1.0 的内容,浏览器在请求资源时,服务器在响应头中携带该参数便可以设置该资源的过期时间,这个过期时间是一个绝对的时间值(如 2017年12月8日),在过期时间之内,浏览器会从本地直接缓存读取资源。
    2.Cache-Control:Max-Age=Number
    和 Expires 类似,该响应头也是用来描述缓存资源的过期时间,和 Expires 不同的是,这个过期时间是一个相对值,表示在某个时间段内有效(如 1天内有效)。在重复请求该资源时,会根据当前时间的时间戳和第一次请求到该资源时的时间戳的差值,和 Max-Age 的值进行对比以判断资源是否过期, 再决定是从本地缓存中读取资源还是向服务器重新发起请求。

    协商缓存

    前面说到,缓存是有过期时间的,当某个资源的缓存过期时,就会再次向服务器发起请求,但这个请求一定会让服务器重新返回一份资源吗?并不一定是这样,浏览器是需要分条件进行操作的:

    • 如果该资源没有缓存协商,会直接向服务器重新请求一份
    • 如果该资源有缓存协商,浏览器会先和服务器进行协商,再决定使用本地的资源还是重新向服务器请求

    为什么需要缓存协商呢?这是因为某些缓存资源即使在过期时间到期之后,资源的内容仍没有发生变化,这种情况下是没有必要再次向服务器请求该资源的,直接使用本地的缓存就可以了。
    在第一次请求资源时,服务器可以在响应头中携带 Etag 或者 Last-Modified,表示该资源是可以进行缓存协商的,如果在响应某个资源时带上了这两个头中的任意一个,当该资源过期以后,浏览器会首先询问服务器该资源是否需要更新,再进行后续的操作。
    对于 Etag 和 Last-Modified,它们代表了两种不同的缓存策略,分别是 Etag/If-None-Match 策略和 Last-Modified/If-Modified-Since 策略。这两个策略在后面进行介绍。

    总结一下,在浏览器第一次请求资源时,除了获取资源本身,还从响应头中获取了一些缓存相关的信息,在资源过期时,会根据这些缓存相关的信息进行操作。
    下面是浏览器第一次请求资源时的一个流程图:


    第一次请求资源.png

    缓存策略

    前面在说缓存类型的时候,提到了 Etag/If-None-Match 和 Modified/If-Modified-Since 这两种缓存策略,它们都是协商缓存上的策略。

    Etag/If-None-Match

    Etag 是 Entity tag 的简写,可以将其看作资源的一个唯一标识,当资源的内容发生变化时,这个唯一标识就改变了,如果资源的内容一直不变,这个唯一标识也就不变。
    浏览器第一次请求资源时,服务器可以在响应头中带上 Etag,其值就是该资源的唯一标识符。当资源过期时,因为有了 Etag,浏览器不会直接请求资源,而是会和服务器进行缓存协商。浏览器会在请求头中带上 If-None-Match,其值就是第一次请求该资源是服务器返回的资源唯一标识符。服务器收到请求后,会根据请求头中的 If-None-Match 携带的唯一标识符和服务器上的资源唯一标识符进行对比,如果资源没有发生改变,服务器返回 304,浏览器直接从本地缓存中读取。如果资源发生改变了,服务器会返回 200,浏览器重新请求该资源。

    Modified/If-Modified-Since

    同 Etag/If-None-Match 策略,Modified/If-Modified-Since 也是根据资源是否发生变化来告诉浏览器是使用本地缓存还是重新向服务器请求,和 Etag/If-None-Match 策略不同的是,Modified/If-Modified-Since 策略着眼点不在于文件的内容而是文件的修改时间。在第一次请求资源时,服务器会在响应头中携带 Modified,其值是最后一次修改的时间,当资源过期时,浏览器会和服务器进行缓存协商,浏览器在请求头中携带 If-Modified-Since,其值是第一次请求资源时从响应中获取的 Modified 值,服务器拿到请求头中的 If-Modified-Since 后,根据资源是否被修改再决定向浏览器返回 304 或者 200。

    Etag/If-None-Match 的优势

    现在常用的协商缓存策略是 Etag/If-None-Match 策略,那么 Etag/If-None-Match 策略相比于 Modified/If-Modified-Since 有什么优势呢?Etag/If-None-Match 的出现是为了解决 Modified/If-Modified-Since 难以解决的一些问题,网上有篇文章总结的很好,我直接引用过来:

    • 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新请求。
    • 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒)。
    • 某些服务器不能精确的得到文件的最后修改时间。

    这时,利用Etag能够更加准确的控制缓存,因为Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符。

    浏览器缓存机制流程

    这里有一张浏览器缓存机制的流程图,描述了浏览器在处理缓存资源的整个流程:


    浏览器缓存流程图.png

    这个图主要的内容还是在缓存策略这一块,可以对比前面的知识进行理解。

    附:参考资料
    http协商缓存VS强缓存
    HTTP ETag
    HTTP 缓存

    完。

    相关文章

      网友评论

        本文标题:浏览器缓存机制

        本文链接:https://www.haomeiwen.com/subject/rfdeixtx.html