客户端文件缓存

Dón*_*nal 16 caching

如果我理解正确,broswer根据文件名缓存图像,JS文件等.因此,如果更新一个此类文件(在服务器上),则浏览器将使用缓存副本.

此问题的解决方法是重命名所有文件(作为构建的一部分),以便文件名包含其内容的MD5哈希,例如

foo.js -> foo_AS577688BC87654.js
me.png -> me_32126A88BC3456BB.png
Run Code Online (Sandbox Code Playgroud)

但是,除了重命名文件本身之外,还必须更改对这些文件的所有引用.例如,<img src="me.png"/>应该更改为标记<img src="me_32126A88BC3456BB.png"/>.

显然,这可能变得非常复杂,特别是当您考虑可以在服务器端代码中动态创建对这些文件的引用时.

当然,一种解决方案是使用HTTP头完全禁用浏览器(以及服务器和浏览器之间的任何缓存)的缓存.但是,没有缓存会产生一系列问题.

有更好的解决方案吗?

谢谢,唐

PJP*_*PJP 16

最佳解决方案似乎是通过附加上次修改时间来版本文件名.

您可以这样做:向Apache配置添加重写规则,如下所示:

RewriteRule ^(.+)\.(.+)\.(js|css|jpg|png|gif)$ $1.$3
Run Code Online (Sandbox Code Playgroud)

这会将任何"版本化"的URL重定向到"正常"的URL.我们的想法是保持您的文件名相同,但要从缓存中受益.对于某些不使用参数缓存URL的代理,将参数附加到URL的解决方案将不是最佳的.

然后,而不是写:

<img src="image.png" />
Run Code Online (Sandbox Code Playgroud)

只需调用PHP函数:

<img src="<?php versionFile('image.png'); ?>" />
Run Code Online (Sandbox Code Playgroud)

使用versionFile()看起来像这样:

function versionFile($file){
    $path = pathinfo($file);
    $ver = '.'.filemtime($_SERVER['DOCUMENT_ROOT'].$file).'.';
    echo $path['dirname'].'/'.str_replace('.', $ver, $path['basename']);
}
Run Code Online (Sandbox Code Playgroud)

就是这样!浏览器将要求image.123456789.png,Apache会将其重定向到image.png,因此您将在所有情况下从缓存中受益,并且不会有任何过时的问题,而不必费心去文件名版本控制.

您可以在此处查看此技术的详细说明:http://particletree.com/notebook/automatically-version-your-css-and-javascript-files/


Nak*_*nch 9

为什么不添加查询字符串"版本"号并每次更新版本?

foo.js - > foo.js?version = 5

在构建期间仍有一些工作要更新版本号,但文件名不需要更改.

  • 如果您关心缓存,查询字符串是一个坏主意,因为大多数代理服务器不会使用"?"缓存资源.在他们的URL中.请参阅http://code.google.com/speed/page-speed/docs/caching.html. (4认同)
  • 保罗 - 我认为该页面上的建议不完整.RFC 2616的第13.9节(HTTP 1.1规范)似乎暗示如果有一个显式的Expires头,查询字符串可以是可缓存的,所以也许使用查询字符串就可以了.但是,这并不意味着所有缓存都会尊重这一点,所以我可能会坚持自己修改文件名. (2认同)

Pau*_*vis 6

重命名资源是可行的方法,尽管我们使用内部版本号并将其嵌入文件名而不是MD5哈希

foo.js -> foo.123.js
Run Code Online (Sandbox Code Playgroud)

因为这意味着您可以以确定的方式重命名所有资源并在运行时解决.

然后,我们使用自定义控件根据存储在应用程序设置中的内部版本号生成页面加载时资源的链接.