美文网首页
网站优化:浏览器缓存控制简介及配置策略

网站优化:浏览器缓存控制简介及配置策略

作者: 滚石_c2a6 | 来源:发表于2017-12-28 15:26 被阅读4次

zz:https://www.renfei.org/blog/http-caching.html
每次访问网页,通常浏览器会从服务器下载所需的资源,例如 HTML 文档、图片、CSS、JavaScript,甚至包括字体文件等。这里面的许多文件(例如图片)都是很少变动的,如果每次都要从服务器重新下载,会不必要地增加网页载入时间,同时也会对服务器造成一定压力。通过合理配置缓存策略,可令浏览器以某种方式把这些静态的文件缓存起来,下次请求同一资源时,直接使用本地存储的副本,而不是从服务器重新下载。

启用缓存至少有两点显而易见的好处:

  • 减少页面加载时间
  • 减少服务器负载

浏览器是否使用缓存、缓存多久,是由服务器控制的。准确来说,当浏览器请求一个网页(或者其他资源)时,服务器发回的响应的「响应头」部分的某些字段指明了有关缓存的关键信息。

Cache-Control

Cache-ControlHTTP 响应头是 HTTP 1.1 协议新增的指令,每个资源都可以通过设定 Cache-Control 来建立缓存策略。通常,可为它指定一个max-age,表示缓存的最长时间,单位为秒。例如,若设定Cache-Control: max-age=604800,则表示这个资源的有效时间为 7 天。浏览器第一次获取这个资源后,7 天之内若再次请求,通常都不会与服务器进行任何通信,而是直接使用本地副本。

此外,还可以为 Cache-Control 指定publicprivate标记。如果使用 private,则表示该资源仅仅属于发出请求的最终用户,这将禁止中间服务器(如代理服务器)缓存此类资源。对于包含用户个人信息的文件(如一个包含用户名的 HTML 文档),可以设置 private,一方面由于这些缓存对其他用户来说没有任何意义,另一方面用户可能不希望相关文件储存在不受信任的服务器上。需要指出的是,private 并不会使得缓存更加安全,它同样会传给中间服务器(如果网站对于传输的安全性要求很高,应该使用传输层安全措施)。对于 public,则允许所有服务器缓存该资源。通常情况下,对于所有人都可以访问的资源(例如网站的 logo、图片、脚本等),Cache-Control 设为 public 是合理的。

Expires

同样是用来控制缓存,Expires响应头从另一个角度——指明缓存的具体过期日期,来控制资源何时过期。在过期时间以内,若再次发起请求,通常浏览器都不会与服务器进行任何通信,而是直接使用本地副本。Apache 服务器允许以多种方式,例如基于该资源的访问时间或上次修改时间来设定 Expires 的值。注意,这里的时间一律使用格林威治时间(Greenwich Mean Time, GMT),而非本地时间。

当 Expires 和 Cache-Control 同时出现时,通常后者会覆盖前者的设定。由于 Expires 对用户的系统时间有所依赖,因此通常认为使用 Cache-Control 是更好的选择(基本上所有的浏览器都支持 Cache-Control 指令)。

Last-Modified 和 ETag

服务器可在 HTTP 返回头中包含Last-Modified字段或者ETag字段。Last-Modified 表示被请求资源在服务器端的上次修改时间,而 ETag 则是一个唯一文件标识符,每次文件修改后都会生成一个新的 ETag。服务器通过向浏览器发送这两个字段,来告知浏览器其获得的资源的版本。

无论通过 Cache-Control 还是 Expires 设置缓存,在过期时间以内,当用户点击浏览器刷新按钮时,为了确保用户所加载的资源是最新的,大部分浏览器不会再直接使用缓存中的数据,而是发出一个条件请求(Conditional GET Request)。对于这类请求,浏览器会在请求头中包含If-Modified-SinceIf-None-Match字段。前者即浏览器当初得到的 Last-Modified;后者即浏览器当初得到的 ETag。当服务器发现资源的更新时间晚于 If-Modified-Since 所提供的时间,或者资源在服务器端当前的 ETag 和 If-None-Match 提供的不符时,会响应整个资源,否则只会响应一个 304 Not Modified 状态码(因此浏览器将不需要重新下载整个资源)。这种机制可以最大程度上减少数据下载量。此外,如果缓存的资源已过期,浏览器通常有两种选择:重新下载这个资源,或发出一个条件请求。很多浏览器都会采取后者,以节约资源。

由于 Last-Modified 和 ETag 的作用是相同的(均为向服务器验证资源是否最新),因此只使用一个即可。通常认为 Last-Modified 更好(它和 Expires 不同,由服务器生成,不依赖浏览器端时间)。

我的网站启用缓存了吗?

用浏览器的开发者工具或插件查看

为了确定是否启用了缓存,只需要检查服务器发回的「响应头」就可以。许多浏览器以及工具都可以检查这些信息,我们以 Firefox 的插件 Firebug 为例。如图所示:

cache-optimization-1

下面再来看一个没有启用缓存的资源的例子:

cache-optimization-2

没有包含Cache-Control以及Expires信息。

在线检测

也有一些方便的在线检测服务,用于对网站速度给出建议,其中就会检测缓存设置情况。比如 Yahoo! 公司的 YSlow,以及百度站长工具等,都有相应的功能。大家可以去百度那里检测一下,目前是不需要登录即可检测的。

使用缓存的策略

为静态资源设置长缓存时间

有些资源是很长时间不会改变的,比如网站的 logo 图片、jQuery 库、字体等,因此可以为它们设定「永不过期」的缓存时间,例如设定为 10 年。

确保文件修改生效

有些时候我们会修改一些资源,比如更新了 jQuery 版本,或网站的 CSS 样式。如果这些资源已经被缓存,那么除非用户手工刷新页面,否则要等缓存自然过期之后用户才会获得新版本。如何在这种情况下强制浏览器重新下载呢?最有效的一个办法就是在这类资源的文件名中包含版本信息,并在更改之后对应地修改文件名。浏览器发现文件更换后,自然无法使用缓存,而会重新下载。

对于 HTML 文档谨慎设定过期时间

大部分情况下,对于其他图片、CSS、JavaScript 等资源的请求都来自一个单一的 HTML 文档。对于这类页面通常应该设定比较短的过期时间,或者干脆不设定。因为如果这类页面被缓存,那么页面中包含的资源的文件名等等信息都会一并被缓存,导致对它的更新难以确保立即对用户生效。

引用静态资源时,不要使用 Query String

Query String 就是例如?key=val的字符串,如

<script src="/static/js/func.js?v=a87ff8"></script>

这会阻止一部分较老的浏览器(包括 IE6 )对该资源进行缓存。

设定缓存的方法

对于 Apache 服务器,可以通过

mod_expires

模块来设定ExpiresHTTP 头或Cache-ControlHTTP 头的max-age指令。编辑相应目录下的

.htaccess

文件,或直接对 Apache 的配置文件(根据服务器系统版本不同,可能为httpd.confapache2.conf等)作出修改。

分文件类别设定

使用ExpiresByType可以按照文件的 MIME Type 设定某一类文件的过期日期。例如:

<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType text/css                "access plus 1 week"
    ExpiresByType application/javascript  "access plus 2 weeks"
    ExpiresByType image/x-icon            "access plus 6 months"
    ExpiresByType image/gif               "access plus 6 months"
    ExpiresByType image/png               "access plus 6 months"
    ExpiresByType image/jpeg              "access plus 6 months"
    ExpiresByType video/x-flv             "access plus 6 months"
    ExpiresByType application/pdf         "access plus 6 months"
</IfModule>

其中access plus 1 week表示将缓存过期设置为访问时间(即当前时间)之后的一周。如果将access替换为modification,则缓存过期会被设定为文件修改时间之后的一周。可以使用的时间单位包括:

  • years
  • months
  • weeks
  • days
  • hours
  • minutes
  • seconds

不同的时间也可以进行组合,例如:

ExpiresByType text/html "access plus 1 month 15 days 2 hours"
ExpiresByType image/gif "modification plus 5 hours 3 minutes"

根据文件扩展名进行设置

如果希望根据扩展名来指定缓存规则,可以使用FilesMatch配合正则表达式。为了简洁,我这里只规定了ExpiresDefault。它的优先级很低,只会在对应文件没有任何其他规则能够匹配(包括上层目录下的缓存规则)时生效。

<IfModule mod_expires.c>
    <FilesMatch "\.(css|js)$">
        ExpiresActive on 
        ExpiresDefault "access plus 1 week"
    </FilesMatch>
</IfModule>

对某些文件设定

同理,也可以对某些文件启用特定的缓存策略。注意,文件名中的点(.)是需要转义的。

<IfModule mod_expires.c>
    <FilesMatch "^(example\.css|example\.js)$">
        ExpiresActive on 
        ExpiresDefault "access plus 1 week"
    </FilesMatch>
</IfModule>

对某一文件夹下的所有文件设定

对于静态文件,一个比较方便的做法是将它们全部放到一个目录下,并对该目录下的所有文件设定。但是,此处需要注意防止其他规则将ExpiresDefault覆盖掉。

<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault "access plus 10 years"
</IfModule>

有用的工具及参考资料

  1. Cache-Control header checker(可检测给定的地址是否启用了 Cache-Control,还会教你如何设定)
  2. Caching Tutorial for Web Authors and Webmasters
  3. HTTP 缓存 - Web Fundamentals(来自 Google Developers)
  4. 百度站长工具-页面优化建议
  5. h5bp/server-configs(HTML5 Boilerplate 提供了所有最流行的服务器的配置文件样例)

相关文章

  • 网站优化:浏览器缓存控制简介及配置策略

    zz:https://www.renfei.org/blog/http-caching.html每次访问网页,通常...

  • web 前端缓存

    标签: 缓存优化 浏览器缓存策略 在此输入正文

  • Redis入门到高可用-10.缓存的使用与优化

    1.概要 缓存的收益与成本 缓存更新策略 缓存粒度控制 缓存穿透优化 无底洞问题优化 缓存雪崩优化 热点key重建...

  • 浏览器缓存策略

    在优化网站性能的时候,浏览器缓存是一个很重要的策略,他会去缓存一些很少更新的图片资源,js资源等。减少浏览器和服务...

  • 简述http缓存

    简介 网站性能第一优化定律:优先考虑使用缓存优化性能。合理的使用缓存,对网站的性能优化的意义重大。以下对于缓存,都...

  • 第十章-Redis缓存和优化

    一. 缓存的收益和分析 二. 缓存的更新策略 三. 缓存粒度控制 四. 缓存穿透优化 五. 无底洞问题优化 六. ...

  • 前端性能优化-下

    优化策略 DNS DNS各个系统本身的设计已经做了很多的优化,比如浏览器的dns缓存记录,计算机的本地dns缓存等...

  • 第11章 缓存设计

    主要内容如下: 缓存的收益和成本分析 缓存更新策略的选择和使用场景 缓存粒度控制方法 穿透问题优化 无底洞问题优化...

  • 电商高并发秒杀4 缓存库存异步化与事务型消息

    1、高效交易验证 用户风控策略优化:策略缓存模型优化 策略缓存模型化,将对应的风控内容做到redis缓存里面,例如...

  • 一日一学_okhttp(本地缓存)

    在学习okhttp缓存策略之前,我先思考了web前端浏览器缓存的策略。浏览器缓存(客户端缓存),它分为强缓存和协商...

网友评论

      本文标题:网站优化:浏览器缓存控制简介及配置策略

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