我注意到一些浏览器(特别是 Firefox 和 Opera )非常热衷于使用 .css 和 .js 文件的缓存副本,甚至在浏览器 session 。当您更新这些文件之一时,这会导致出现问题,但用户的浏览器继续使用缓存的副本。
强制用户浏览器在文件更改时重新加载文件的最优雅方法是什么?
理想情况下,该解决方案不会强制浏览器在每次访问页面时重新加载文件。
<小时/>我找到了John Millikin's和 da5id's建议是有用的。事实证明有一个术语:自动版本控制。
我在下面发布了一个新答案,它是我原来的解决方案和约翰的建议的结合。
SCdF 提出的另一个想法是将伪造的查询字符串附加到文件中。 (一些自动使用时间戳作为虚假查询字符串的 Python 代码是 submitted by pi. 。)
但是,对于浏览器是否会缓存带有查询字符串的文件存在一些讨论。 (请记住,我们希望浏览器缓存该文件并在将来访问时使用它。我们只希望它在文件发生更改时再次获取该文件。)
最佳答案
该解决方案是用 PHP 编写的,但它应该很容易适应其他语言。
原始的.htaccess
正则表达式可能会导致json-1.3.js
等文件出现问题。解决方案是仅当末尾正好有 10 位数字时才重写。 (因为 10 位数字涵盖了从 9/9/2001 到 11/20/2286 的所有时间戳。)
首先,我们在.htaccess中使用以下重写规则:
RewriteEngine on
RewriteRule ^(.*)\.[\d]{10}\.(css|js)$ $1.$2 [L]
现在,我们编写以下 PHP 函数:
/**
* Given a file, i.e. /css/base.css, replaces it with a string containing the
* file's mtime, i.e. /css/base.1221534296.css.
*
* @param $file The file to be loaded. works on all type of paths.
*/
function auto_version($file) {
if($file[0] !== '/') {
$file = rtrim(str_replace(DIRECTORY_SEPARATOR, '/', dirname($_SERVER['PHP_SELF'])), '/') . '/' . $file;
}
if (!file_exists($_SERVER['DOCUMENT_ROOT'] . $file))
return $file;
$mtime = filemtime($_SERVER['DOCUMENT_ROOT'] . $file);
return preg_replace('{\\.([^./]+)$}', ".$mtime.\$1", $file);
}
现在,无论您在何处包含 CSS,都可以将其更改为:
<link rel="stylesheet" href="/css/base.css" type="text/css" />
对此:
<link rel="stylesheet" href="<?php echo auto_version('/css/base.css'); ?>" type="text/css" />
这样,您就不必再次修改链接标签,并且用户将始终看到最新的 CSS。浏览器将能够缓存 CSS 文件,但是当您对 CSS 进行任何更改时,浏览器会将其视为新 URL,因此不会使用缓存的副本。
这也适用于图像、网站图标和 JavaScript。基本上任何不是动态生成的东西。
关于caching - 如何强制浏览器重新加载缓存的 CSS 和 JS 文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43655733/