This website requires JavaScript.

Web 性能优化 - 浏览器缓存

2017.11.25 16:06字数 1801阅读 581喜欢 8评论 2

最快的请求,就是没有请求。将之前下载过的的数据缓存并维护好,就可以做到这一点。

所有的缓存都有自己的一套规则,用来决定是否该被缓存,过期时间以及一些其他。

在浏览器缓存里,这套规则是在 HTML meta 标签以及 HTTP 协议头中定义的;

HTML meta

开发人员仅需在 html head 里设置如下 meta 标签

<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Expires" CONTENT="0">

上述标签,告诉浏览器,不缓存资源,每次访问,都到服务器去拉取。
使用很简单,但是只有部分浏览器支持。

HTTP 协议头

从两个方面规定是直接读取缓存,还是从服务器拉取。

  • 控制缓存时间(强缓存),如设置 Expires、Cache-Control 首部;
  • 验证机制(协商缓存),如设置 Last-Modified、ETag 首部。

强缓存

  • Expires:值是一个 GMT(格林尼治时间),比如 Sat, 25 Nov 2017 07:20:50 GMT 来告诉浏览器资源缓存过期时间,如果还没过该时间点则不发请求。

    具有一定的局限性,存在浏览器和服务端时间出现较大误差的情况;此外,你很可能会忘记给某个资源设置一个特定时间,如果返回内容的时候没有更新这个时间,则每个资源都要去服务器拉取,反而增加了负载和相应时间。

  • Cache-Control:为了弥补 Expires 的时间是相对服务器而言,无法保证和客户端时间统一的问题,HTTP 1.1 新增了 Cache-Control 来设置缓存时间。

    Cache-Control 常见的相应头包括:

    • max-age=[秒]:表示在这个时间范围内缓存是新鲜的,无需更新。类似 Expires,不过这个时间是相对的。也就是某次请求成功后多少秒内缓存是新鲜的;
    • public:标记认证的响应才能够被缓存。一般而言,需要认证 HTTP 请求内容会自动私有化(不会被缓存);

    • private:允许缓存专门为某一个用户存储响应,比方说在浏览器中;共享缓存一般不会。

    • no-cache:这个很容易让人产生误解,使人误以为是响应不被缓存。实际上它是会被缓存的,只不过每次在向客户端(浏览器)提供响应数据时,缓存都要向服务器评估缓存响应的有效性。

    • no-store:强制缓存在任何情况下都不要保留任何副本。

两者可以同时设置,但是优先级 Cache-Control > Expires 。

协商缓存

当设置的缓存时间已经过期,此时协商缓存就派上了用场。

  • last-modified/if-modified-since

last-modified:告诉浏览器当前资源的最后修改时间。

if-modified-since:如果浏览器第一次请求时响应中 last-modified为非空,第二次请求同一资源时,会把它作为该项值发送给服务器。根据浏览器发送的修改时间和服务端的修改时间进行对比,一致则说明资源没有改变,服务端返回正文为空的响应,让浏览器从缓存中读取资源。

  • If-None-Match/ETag

ETag: 告诉浏览器当前资源的唯一标实符。

If-None-Match:如果浏览器第一次请求时响应中 ETag 非空,第二次请求同一资源时,会把它作为该项的值发给服务器。服务器接到请求后如果一致(即资源没有修改),则返回 304 Not Modified,否则返回新的资源(200)。

总结