在apache中控制浏览器缓存更改js和css文件的最佳方法?

Sco*_*ott 3 javascript css caching apache2

我们刚刚对网站进行了重新设计,在部署之后,我们必须对控制新外观和感觉的各种 css 和 javascript 文件进行一些小调整。我们遇到的问题之一是浏览器似乎缓存了这些文件,因此用户客户端可能看不到我们所做的一些修复。
我们最初想对文件的 mtime 做一些事情,作为“快速修复”黑客,我们使用 url 参数修改了对这些文件的一些主要调用,该参数使用服务器端 php 附加相关文件的最新 mtime 。但这并没有按计划工作,因为我们的部署系统克隆了一个 git 分支,因此,每个部署最终都会触及每个文件并改变其运行时间。(最终结果是,部署一个小修复最终会告诉客户端浏览器重新加载部署后修改的每个<LINK><Script>标记,无论文件内容是否实际上已更改。)

我正在查看 apache FileETag,但它似乎使用 mtime、大小和 inode。(我希望找到类似校验和的东西) mtime 显然不适用于我们使用的部署方法,如果更改不改变文件的长度,则大小可能不会改变。我不太熟悉索引节点信息的工作原理,所以我不确定这是否符合我们的需求。

所以我想知道是否有人还有其他建议,告诉客户端浏览器仅在文件内容实际更改时重新加载文件。

Bar*_*ard 5

因此,人们经常混淆缓存的两个重要区别:

  1. 浏览器应缓存资源多长时间。这通常是由 Cache-Control 标头驱动的(尽管有时仍然使用旧的 Expires 标头)。在此期间,不会向服务器发出任何请求,直到资源被视为旧的。这是您尽可能想要的,因为它可以避免由带宽和延迟引起的问题。

  2. 应该如何重新验证过期资源。这是由 Last-Modified 或 ETag 标头驱动的。这里向服务器发出请求,服务器返回 304 响应,表示“我不会向您发送该文件的新版本,因为根据您提供给我的上次修改或 ETag 详细信息,您仍然拥有该副本仍然是最新版本,所以考虑一下这对另一位有好处”。这实际上只对大型资源(例如大图像或视频)有用。CSS 和 JS 文件通常较小,下载它们的时间并不比发送 304 响应多多少,因此在这里使用 304 并没有真正获得太多好处。从服务器返回任何响应(无论是 304 还是资源本身)的延迟是主要瓶颈,只能通过将文件在缓存中保留更长时间来避免。

您似乎想使用一些验证技术(修改时间或 ETag)来为您提供良好的缓存,但当您确实更改某些内容时会立即重新加载,但这不是最好的方法,因为您基本上只能在它是时使用上面的第二部分首先这会给你带来好处。顺便说一句,关于为什么延迟是问题的好文章:http://www.nateberkopec.com/2015/11/05/page-weight-doesnt-matter.html。该文章中还有很多其他很好的信息,因此建议您全部阅读。

因此,您最终需要非常长的 Cache-Controls,因此在第一次下载后它会保留在缓存中。但是,当您进行更改时,您希望强制用户尽快重新加载。这些是相反的要求。

因此,您的选择是要么使用缓存清除技术,要么基本上忽略该问题。

缓存清除技术基本上会欺骗浏览器,使其认为它正在请求不同的资源。例如在 URL 中添加参数。CSS 技巧在这里有一个关于各种技术的精彩页面:https://css-tricks.com/strategies-for-cache-busting-css/。基于您的部署技术无法基于 mtime 工作,因此您确实需要在此处添加版本号,但这有多容易取决于您创建页面的方式以及您使用的构建过程。

另一种选择是忽略该问题,直到资源过期。这可能看起来很奇怪,但越来越成为我的首选选择,所以让我解释一下原因。我所做的就是为容易发生变化的关键资源(例如 HTML、CSS 和 JS)设置一个非常短的到期时间。假设一到三个小时。然后接受人们将在这段时间内获得缓存的、可能过时的资源。大多数建议的有效期很长,希望将您的页面缓存一段时间,但考虑到缓存并不像某些人想象的那么大(再次参见上面引用的文章),恕我直言,除了非常频繁的情况外,大多数情况下都看不到好处访客。因此,您会遇到长期到期的麻烦,但没有任何好处。使用较短的有效期有几个好处:

  • 没有复杂的缓存清除
  • 除非访问者最近访问过,否则在缓存过期时间内,他们将获得最新的资源。
  • 您现在也可以缓存静态页面。大多数缓存清除技术取决于每次下载的 HTML(因此您可以检查页面所需的资源是否使用了任何缓存清除技术),但如果浏览到主页,然后浏览另一个页面,然后多次返回主页那么每次都下载主页就没有意义了!为什么不缓存它并在浏览时具有即时响应能力?除非您是新闻网站,否则 99% 的情况下都可能会使用旧主页。使用较短的过期时间可以让您缓存 HTML 页面。
  • 每次初始访问可能会较慢,但一旦不再妨碍,它将缓存资源并感觉快速浏览(假设页面共享大量资源)。现在,最初的页面加载很重要 - 不要误会我的意思,但是考虑到缓存大小,无论如何,这种额外的负面影响都是有争议的,并且您的资源很可能已经被强制从缓存中移出。

缺点是:

  • 发布期间,现场人员的页面可能会中断。例如,他们访问主页并下载 CSS,然后您使用新的 HTML 和 CSS 发布所有页面,然后相同的访问者查看另一个页面,因此获得新的 HTML,但仍然使用缓存的旧 CSS。这件事有多大,由你来决定。就我个人而言,对于重大更改,我对 CSS 文件 (stylesv2.css) 进行版本控制,但对于调整,我只能忍受这一点。很少会导致问题,并且用户经常会在页面看起来错误时重新加载页面。显然,对于某些网站来说,这可能有点简单,这可能不是一个选择。
  • 所有性能工具(例如Google的Page Insights)都会标记您的到期时间较短 - 即使您出于充分的理由明确做出了该选择 - 因为他们(在我看来是错误的)认为较长的到期时间总是更好。比什么都烦人。

在我看来,ETag 非常无用,因为它们的实施很差。Apache 默认情况下使用文件大小和修改时间的组合 - 正如您正确指出的那样,这可能无法识别文件内容是否已更改。Inode 基本上就是磁盘上的文件引用,所以类似。在使用负载均衡器和多个 Web 服务器时也不建议这样做,因为每个服务器的 inode 都会不同(这就是默认情况下不再使用它的原因)。内容的散列会更好(尽管可能会更慢)。但 Apache 上的 Etags 的主要问题是,当您对数据进行 gzip 压缩时(您应该这样做),它们不起作用!请参阅我的博客文章: https: //www.tunetheweb.com/performance/http-performance-headers/etag/。因此,您不应该在 Apache 上使用 Etag。而且,如上所述,它们对于小型资源(例如您希望压缩的文本资源)来说相当无用。最后修改的几乎一样好,并且没有 gzip 压缩资源的错误。

拥有适当的缓存是您可以对站点进行的最大性能改进之一。如果没有它,当您浏览网站时,无论您的服务器或访问者计算机的速度有多快,网站都会感觉缓慢且滞后。有了它,即使服务器速度很慢,网站也会感觉敏捷且响应迅速。然而,正如您所注意到的,它确实使事情变得复杂,因此需要好好思考如何正确设置它。

我在这里更详细地介绍了如何配置 Apache: https: //www.tunetheweb.com/performance/http-performance-headers/caching/

希望这对您有所帮助 - 即使它有点啰嗦,而且不幸的是并没有给您提供您无疑正在寻找的快速解决方案!