浏览器缓存机制

作者: tency小七 | 来源:发表于2018-08-14 12:34 被阅读6次

    参考以下文章
    https://segmentfault.com/a/1190000006741200
    https://github.com/zuopf769/notebook/tree/master/fe/%E5%89%8D%E7%AB%AF%E5%BF%85%E9%A1%BB%E8%A6%81%E6%87%82%E7%9A%84%E6%B5%8F%E8%A7%88%E5%99%A8%E7%BC%93%E5%AD%98%E6%9C%BA%E5%88%B6

    注意,我们讨论的所有关于缓存资源的问题,都仅仅针对GET请求。而对于POST, DELETE, PUT这类行为性操作通常不做任何缓存。

    浏览器缓存==客户端缓存

    浏览器请求静态资源的过程

    下面这张图展示了某一网站,对不同资源的请求结果,其中可以看到有的资源直接从缓存中读取,有的资源跟服务器进行了再验证,有的资源重新从服务器端获取。


    浏览器缓存分为两种,分别是强制缓存协商缓存

    强制缓存

    浏览器在加载资源时,会根据这个资源的http请求头去看是否命中强缓存,如果命中强缓存就直接用浏览器缓存的资源,这个过程中没有发请求给服务器

    协商缓存

    这个过程有发请求给服务器,服务器返回304,不会返回数据,还是继续用浏览器缓存的数据。

    与强制缓存有关的两个属性

    Cache-Control和Expires

    • Cache-Control是HTTP1.1中新增的响应头
    • Expires是HTTP1.0中的响应头
    • Cache-Control使用的是相对时间
    • Expires指定的是具体的过期日期而不是秒数。因为很多服务器跟客户端存在时钟不一致的情况,所以最好还是使用Cache-Control.
    • Cache-Control和Expires同时使用的话,Cache-Control会覆盖Expires

    Cache-Control有什么属性

    • max-age(单位为s)

    指定设置缓存最大的有效时间,定义的是时间长短。当浏览器向服务器发送请求后,在max-age这段时间里浏览器就不会再向服务器发送请求了。

    • public

    指定响应可以在代理缓存中被缓存,于是可以被多用户共享。如果没有明确指定private,则默认为public

    • private

    响应只能在私有缓存中被缓存,不能放在代理缓存上。对一些用户信息敏感的资源,通常需要设置为private。

    • no-cache

    表示必须先与服务器确认资源是否被更改过(依靠If-None-Match和Etag),然后再决定是否使用本地缓存。

    • no-store

    绝对禁止缓存任何资源,也就是说每次用户请求资源时,都会向服务器发送一个请求,每次都会下载完整的资源。通常用于机密性资源。

    HTTP通过缓存将服务器资源的副本保留一段时间,这段时间称为新鲜度限值。这在一段时间内请求相同资源不会再通过服务器,也就是不会向服务器发起请求。HTTP协议中Cache-Control 和 Expires可以用来设置新鲜度的限值,前者是HTTP1.1中新增的响应头,后者是HTTP1.0中的响应头。二者所做的事时都是相同的,但由于Cache-Control使用的是相对时间,而Expires可能存在客户端与服务器端时间不一样的问题,所以我们更倾向于选择Cache-Control。

    当expire和cache-control都过期了,也就是过了这个新鲜度限值了,我们这个时候就要用到协商缓存了,这个时候就要跟服务器进行验证了。

    • 如果资源发生变化,则需要取得新的资源,并在缓存中替换旧资源。
    • 如果资源没有发生变化,缓存只需要获取新的响应头,和一个新的过期时间,对缓存中的资源过期时间进行更新即可。
      HTTP1.1推荐使用的验证方式是If-None-Match/Etag,在HTTP1.0中则使用If-Modified-Since/Last-Modified。
    与协商缓存有关的两个属性

    If-None-Match/Etag或者If-Modified-Since/Last-Modified

    • Etag是HTTP1.1推荐使用的验证方式,是指根据实体内容生成一段hash字符串,标识资源的状态,由服务端产生。浏览器会将这串字符串传回服务器,验证资源是否已经修改,如果没有修改,过程如下:


      image.png
    • ETag值通常由服务器端计算,并在响应客户端请求时将它返回给客户端
    • If-Modified-Since与Last-Modified验证过程与etag类似。
      这两个方式来验证时会存在下面问题:
      有些文档资源周期性的被重写,但实际内容没有改变。此时文件元数据中会显示文件最近的修改日期与If-Modified-Since不相同,导致不必要的响应。
      有些文档资源被修改了,但修改内容并不重要,不需要所有的缓存都更新(比如代码注释)

    总结

    • 浏览器端缓存分为200 from cache和304 not modified
    • HTTP协议中Cache-Control 和 Expires可以用来设置新鲜度的限值,前者是HTTP1.1中新增的响应头,后者是HTTP1.0中的响应头。
    • max-age(单位为s)而Expires指定的是具体的过期日期而不是秒数
    • Cache-Control和Expires同时使用的话,Cache-Control会覆盖Expires
      客户端不用关心ETag值如何产生,只要服务在资源状态发生变更的情况下将ETag值发送给它就行
    • Apache默认通过FileEtag中FileEtag INode Mtime Size的配置自动生成ETag(当然也可以通过用户自定义的方式)。
    • ETag常与If-None-Match或者If-Match一起,由客户端通过HTTP头信息(包括ETag值)发送给服务端处理。
    • Last-Modified常与If-Modified-Since一起由客户端将Last-Modified值包括在HTTP头信息中发给服务端进行处理。
    • 有些文档资源周期性的被重写,但实际内容没有改变。此时文件元数据中会显示文件最近的修改日期与If-Modified-Since不相同,导致不必要的响应。

    相关文章

      网友评论

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

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