zoukankan      html  css  js  c++  java
  • 浏览器缓存

    浏览器缓存

    注:MS总被问的问题,也算是高频问题,即使不问,在问你浏览器加载URL的时候可以在讲完CDN、DNS后把这个加上,然后就是域名解析得到IP地址之后,浏览器与服务器进行连接,中间涉及tcp/ip的连接与断开,可以谈连接三次握手、断开四次挥手,如果是https协议的话,可以说下多的是什么东西等等,浏览器请求资源可以把浏览器缓存的理解加上,浏览器的进程和线程是怎么工作的,之后也就是浏览器对请求回来的资源进行解析,其中htmlPaser、cssPaser对文件的解析然后合并成renderTree,然后绘制到页面上的过程,这里还可以加上重排重绘的理解(什么情况会造成重排重绘,怎样避免重排重绘等),这样回答浏览器中输入URL后都做了什么基本上回答的点都有了。(其实我能想到回答的点也不全)如果还了解什么是后端的分布式等知识,把这些都加上估计会更加分反正我是不怎么懂。

    当浏览器请求一个网站的时候,会加载各种各样的资源,比如:HTML文档、图片、CSS和JS等文件。对于一些不经常变得内容,浏览器会将它们保存在本地的文件中,下次访问相同的网站的时候,直接加载这些资源,加速访问。这些被浏览器保存的文件就被成为缓存(不是指cookie或者localstorage)。第一次打开网站的后,如果再次刷新页面。会发现浏览器加载的众多资源中,有一部分size有具体数据值,然而还有一部分请求并没有显示文件的大小(比如JS文件、CSS文件等),而是显示from disk cache 或者 from memory cache 字样。这就说明了,该资源直接从本地硬盘或者浏览器内存中读取,并没有请求到服务器。

    浏览器缓存机制可分为强缓存和协商缓存

    1. 浏览器在加载资源时,先根据这个资源的一些HTTP Header判断它是否命中强缓存,强缓存如果命中浏览器直接从自己的缓存中读取资源,不会发请求到服务器。
    2. 当强缓存没有命中的时候,浏览器一定会发送一个请求到服务器,通过服务器端依据资源的另外一个HTTP Header验证这个资源是否命中协商缓存,如果协商缓存命中服务器会将这个请求返回,但是不会返回这个资源的数据,而是告诉客户端可以直接从缓存中加载这个资源
    3. 强缓存和协商缓存的共同点是:如果命中都是从客户端缓存中加载资源而不是从服务器端加载资源;区别:强缓存不发送请求到服务器,协商缓存会发送请求到服务器。
    4. 当协商缓存也没有命中的时候,浏览器直接从服务器端加载资源数据。

    强缓存(强制缓存)

    Expires是服务器端响应请求时用来规定资源的失效时间,Expires是HTTP1.0的产物。
    缺点:到期时间由服务端生成,但是客户端时间可能跟服务端时间有误差,这就会导致缓存命中的误差。所以HTTP1.1的版本中,使用Cache-Control替代。在当下的前端实践中我们继续使用expires的唯一目的就是向下兼容。

    Cache-Control常见的取值有private、public、no-cache、max-age、no-store,默认为private。
    private:内容只缓存到私有缓存中(仅客户端可以缓存,代理服务器不可以缓存)
    public:所有内容都将被缓存(客户端和代理服务器端都可缓存)
    max-age=xxx:缓存的内容将在xxx秒后失效
    s-maxage:用于表示cache服务器上缓存的有效时间,并只对public缓存有效。s-maxage仅在代理服务器中生效,客户端我们只考虑max-age
    no-cache:每一次发起请求都不会再去询问浏览器的缓存情况,而是直接向服务端去确认该资源是否过期(即协商缓存)
    no-store:所有的内容都不会被缓存,强缓存、协商缓存(对比缓存)都不会被触发,所有的内容都不会被缓存或Internet临时文件中
    must-revalidation/proxy-recalidation:如果缓存的内容失效,请求必须发送到服务器/代理以进行重新验证。

    Pragma
    Pragma:no-cache,跟Cache-Control: no-cache相同。
    Pragma: no-cache兼容http 1.0 ,Cache-Control: no-cache是http 1.1提供的。
    因此,Pragma: no-cache可以应用到http 1.0 和http 1.1,而Cache-Control: no-cache只能应用于http 1.1。
    Pragma是旧产物,已经逐步抛弃,有些网站为了向下兼容还保留了这两个字段。
    优先级从高到低是 Pragma -> Cache-Control -> Expires

    协商缓存(对比缓存)

    Last-Modified / If-Modified-Since

    Last-Modified:服务器在响应请求时,告诉浏览器资源的最后修改时间。
    eg:Last-Modified: Fri, 27 Oct 2017 06:35:57 GMT

    If-Modified-Since:再次请求服务器时,通过此字段通知服务器上次请求时,服务器返回的资源最后修改时间。服务器收到请求后发现有头 If-Modified-Since则与被请求资源的最后修改时间进行比对。若资源的最后修改时间大于 If-Modified-Since,说明资源又被改动过,则响应资源内容,返回状态码200;若资源的最后修改时间小于或等于If-Modified-Since,说明资源无新修改,则响应HTTP 304,告知浏览器继续使用所保存的cache。
    eg:If-Modified-Since: Fri, 27 Oct 2017 06:35:57 GMT

    Etag / If-None-Match(优先级高于 Last-Modified / If-Modified-Since)

    Etag:服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器决定),这个标识字符串是基于文件内容编码的,只要文件内容不同,它们对应的 Etag就是不同的,反之亦然。因此 Etag 能够精准地感知文件的变化。
    eg:ETag: W/"2a3b-1602480f459"
    If-None-Match:再次请求服务器时,通过此字段通知服务器客户段缓存数据的唯一标识。服务器收到请求后发现有头If-None-Match 则与被请求资源的唯一标识进行比对,不同,说明资源又被改动过,则响应整片资源内容,返回状态码200;相同,说明资源无新修改,则响应HTTP 304,告知浏览器继续使用所保存的cache。
    eg:If-None-Match: W/"2a3b-1602480f459"

    HTTP 1.1 中 Etag 的出现主要是为了解决几个 Last-Modified 比较难解决的问题:
    1. Last-Modified 标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内被修改多次的话,它将不能准确标注文件的修改时间;
    2. 如果某些文件会被定期生成,但有时内容并没有任何变化,但 Last-Modified 却改变了,导致文件没法使用缓存;
    3. 有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形;
    Etag也有弊端:
    Etag 的生成过程需要服务器额外付出开销,会影响服务端的性能,这是它的弊端。因此启用 Etag 需要我们审时度势。正如我们刚刚所提到的——Etag 并不能替代Last-Modified,它只能作为 Last-Modified 的补充和强化存在。

    补充:
    我们总是说Etag优先级高于Last-Modified ,但是Etag 其实只是 Last-Modified 的补充和强化。这句话应该是这样理解的:首先,决定用哪个字段是服务器自己的事情,和强制缓存不太一样,所以并没有谁优先级高于谁的说法。但是,作为服务器来说,我直接判断Etag肯定是更快更高效的方法。这也是为什么说它优先级高的原因。那是不是有了Etag就可以不用 Last-Modified了呢,显然是不可以的。毕竟 Etag会消耗服务器性能。所以,针对文件变动,用Last-Modified不能帮我们判断文件是否有效的,我们就用Etag来补充和强化,而针对文件变化比较大,Last-Modified就能很显著的表现的,我们可以不用Etag。

    如果什么缓存策略都没设置,那么浏览器会怎么处理?
    对于这种情况,浏览器会采用一个启发式的算法,通常会取响应头中的 Date 减去 Last-Modified值的 10% 作为缓存时间。
     
     
    用户行为与缓存
    用户操作  Expires/Cache-Control  Last-Modified/Etag
    地址栏回车  有效  有效
    页面链接跳转  有效  有效
    新开窗口   有效  有效
    前进、后退  有效  有效
    F5刷新 无效  有效
    ctrl + F5刷新 无效(重置Cache-Control=no-cache) 无效(请求头丢弃该选项)
    注:F5刷新强缓存无效,协商缓存有效;Ctrl+F5刷新强缓存和协商缓存都无效;相当于我们在浏览器的设置中清空了所有缓存或是刷新按钮右键中”清空缓存并硬性重新加载“


  • 相关阅读:
    webpack打包报错configuration has an unknown property 'mode'
    CSP 201712-4 行车路线(最短路)
    设计模式
    sqlserver 迁移数据
    DataX
    Python 对接WebService
    IOS APP打包流程
    nginxUI
    ROS脚本-下线时判断在线数量进行重拨号
    bash 字符串截取的8种方法
  • 原文地址:https://www.cnblogs.com/zhenjianyu/p/12965571.html
Copyright © 2011-2022 走看看