强制浏览器在更新后重新加载css

时间:2012-04-16 01:03:11

标签: php css cakephp caching browser-state

当我更新服务器上的css文件时,许多客户端浏览器将继续使用旧的缓存css文件加载页面很长一段时间。

在搜索了很多帖子并将不同的想法放在一起之后,我想出了一种似乎最简单和最便宜的方法。

在链接任何css文件的情况下,将href附加文件的最后修改日期的时间戳,如下所示:

<link rel="stylesheet" type="text/css" href="main.css?t=<?=filemtime('main.css')?>" />

我正在使用CakePHP,所以我在布局文件中做的是:

  <? $t = filemtime(CSS . 'main.css'); ?>
  <?=$html->css("schedule.css?t={$t}") ?>

因此,到css文件的链接末尾有一个额外的标记,但只要文件没有被修改就会保持不变。这意味着浏览器将能够像往常一样缓存它。但是,只要文件被修改,链接就会改变,浏览器也不会错过任何一个节拍。

仍然使用这种方法,让人感觉有点脏,因为它不适合用于某些东西。对于正在发送的“消息”没有用处,因为消息的内容很重要,除了识别它的存在。

以下是我的问题:

  1. 是否可以承认客户有可能从浏览器缓存中看到带有过时样式表(或javascript)的修订版HTML?
  2. 这是一个黑客还是一个合法的解决方案?
  3. 有更好的解决方案吗?

2 个答案:

答案 0 :(得分:4)

我认为您的方法没有任何问题。更常见的是,这称为缓存清除或缓存失效。

但是,由于您使用的是诸如:http://site.com/assets/mystyle.css?29320202020之类的网址,因此可能存在CDN问题。 CDN将看到GET参数并认为它是一个动态请求,因此它会向您的服务器询问该文件,这会破坏在CDN中拥有缓存副本的目的。

为什么我要在文件名中包含缓存清除参数:http://site.com/assets/mystyle.2390202202.css。我使用优秀的Assetic library来执行此操作并编写了一些简单的代码,以便我的模板知道它需要mystyle.css并且mystyle.2390202202.css由Assetic动态生成并插入到模板中

这种方法可以让你在处理CDN时很好地缓存破坏功能。


其他可能的解决方案:

  • ETags:浏览器将使用ETag向服务器发送请求(可以将其视为文件的散列),如果文件未更改,服务器将使用未修改的标头响应进行响应。缺点:仍然需要发出HTTP请求。

  • 设置过期标题:服务器将告诉浏览器该文件将在特定日期过期,如果还不是该日期,则浏览器不会从服务器请求副本并使用其本地缓存副本。缺点:如果服务器上的文件在日期之前发生变化,浏览器的用户将需要手动进行硬刷新。

这就是为什么我更喜欢使用缓存清除参数:我可以将文件的expires头设置为在5年后到期。浏览器不应该对该文件发出http请求,除非我更新文件并更改缓存清除参数。

答案 1 :(得分:4)

CakePHP有一个非常简单易用的解决方案。只需取消注释这一行:

//Configure::write('Asset.timestamp', true);

来自core.php

根据该文件,这将

  

将上次修改时间的时间戳应用于静态资产(js,   css,图像)。将附加包含时间的查询字符串参数   该文件已被修改。这对于使浏览器缓存无效非常有用。

这非常简单,大部分时间都可以使用,但并非万无一失。大多数代理都不会使用&#34;?&#34;来缓存资源。在URL中,所以如果你想修复这些情况,你应该实现一个更复杂的解决方案,就像phpdev建议的那样。