浏览器缓存那些事

作者: Android开发哥 | 来源:发表于2017-02-26 14:27 被阅读174次

    什么是浏览器缓存

    浏览器缓存(Browser Caching) 是为了节约网络的资源加速浏览,浏览器在用户磁盘上对最近请求过的文档进行存储,当访问者再次请求这个页面时,浏览器就可以从本地磁盘显示文档,这样就可以加速页面的阅览。

    浏览器缓存是把双刃剑

    优点

    • 减少了冗余的数据传输,节省了网费
    • 减少了服务器的负担,大大提升了网站的性能
    • 加快了客户端加载网页的速度

    缺点

    既然存在了本地,那就意味着远程服务器的修改可能不起作用.往往在本地访问调试远程服务器的时候,会发现修改并没有起效。

    缓存的分类

    缓存协商

    图解

    协商缓存初次请求

    协商缓存初次请求

    协商缓存再次请求

    协商缓存再次请求

    1. 浏览器会先获取该资源缓存的 header 信息,根据其中的 expirescahe-control 判断是否 命中强缓存,若命中则直接从缓存中获取资源,包括缓存的header信息,本次请求不会与服务器进行通信;
    2. 如果没有 命中强缓存,浏览器会发送请求到服务器,该请求会携带第一次请求返回的有关缓存的header 字段信息 (Last-Modified/IF-Modified-Since、Etag/IF-None-Match) ,由服务器根据请求中的相关header信息来对比结果是否命中 协商缓存 ,若命中,则服务器返回新的响应header信息更新缓存中的对应header信息,但是并不返回资源内容,它会告知浏览器可以直接从缓存获取;否则返回最新的资源内容

    协商缓存 就是由服务器来确定缓存资源是否可用,所以客户端与服务器端要通过某种标识 来进行通信,从而让服务器判断请求资源是否可以缓存访问,这主要涉及到下面 两组header字段 ,这两组搭档都是成对出现的,即第一次请求的响应头带上某个字段 (Last-Modified或者Etag) ,则后续请求则会带上对应的请求字段 (If-Modified-Since或者If-None-Match)若响应头没有Last-Modified或者Etag字段,则请求头也不会有对应的字段。

    Last-Modify/If-Modify-Since

    浏览器 第一次请求 一个资源的时候,服务器返回的header中会加上 Last-Modify ,Last-modify是一个时间标识该资源的最后修改时间,例如 Last-Modify: Thu,31 Dec 2037 23:59:59 GMT
    当浏览器 再次请求该资源 时,request的请求头中会包含 If-Modify-Since ,该值为 缓存之前返回的Last-Modify 。服务器收到If-Modify-Since后,根据资源的最后修改时间判断是否命中缓存。
    如果 命中缓存,则返回304 ,并且不会返回资源内容,并且不会返回Last-Modify。

    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跟之前的没有变化。

    Etag存在的意义

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

    强缓存

    强缓存 是利用http的返回头中的 Expires 或者 Cache-Control 两个字段来控制的,用来表示资源的缓存时间。

    Expires

    该字段是http1.0时的规范,它的值为一个绝对时间的GMT格式的时间字符串,比如Expires:Mon,18 Oct 2066 23:59:59GMT。这个时间代表着这个资源的失效时间,在此时间之前,即 命中缓存 。这种方式有一个明显的缺点,由于失效时间是一个绝对时间,所以当服务器与客户端时间偏差较大时,就会导致缓存混乱。

    Cache-Control

    Cache-Control是http1.1时出现的header信息,主要是利用该字段的 max-age 值来进行判断,它是一个相对时间,例如 Cache-Control:max-age=3600 ,代表着资源的有效期是3600秒。cache-control除了该字段外,还有下面几个比较常用的设置值:

    no-cache:不使用本地缓存。需要使用缓存协商,先与服务器确认返回的响应是否被更改,如果之前的响应中存在ETag,那么请求的时候会与服务端验证,如果资源未被更改,则可以避免重新下载。

    no-store:直接禁止游览器缓存数据,每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。

    public:可以被所有的用户缓存,包括终端用户和CDN等中间代理服务器。

    private:只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器对其缓存。

    Cache-Control与Expires可以在服务端配置同时启用,同时启用的时候 Cache-Control优先级比Expires高

    强缓存和协商缓存区别

    获取资源形式 状态码 发送请求到服务器
    强缓存 200(from cache) 否,直接从缓存取
    协商缓存 304(Not Modified) 否通过服务器来告知缓存是否可用

    用户行为对缓存的影响

    用户操作 Expires/Cache-Control Last-Modified/Etag
    地址栏回车 有效 有效
    页面链接跳转 有效 有效
    新开窗口 有效 有效
    前进、后退 有效 有效
    F5/按钮刷新 无效(BR重置max-age=0) 有效
    Ctrl+F5刷新 无效(重置CC=no-cache) 无效(请求头丢弃该选项 )

    解决实际中的缓存问题

    一般是在 url 地址后面加上当前的版本信息.例如 xx/xxx.php?ver=1.1,这样就会根据版本的不同而去更新缓存了.

    相关文章

      网友评论

        本文标题:浏览器缓存那些事

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