静态资源文件的缓存问题
发布网友
发布时间:2022-12-21 20:09
我来回答
共1个回答
热心网友
时间:2023-06-27 17:31
前一阵被人问到一个问题:
相信不少人第一直觉会想到和浏览器缓存有关的一些缓存头,例如:
我们把问题细化一下,修改的文件存在两种情况:
下面这个是知乎中个人头像的缓存情况,可以看到采用了cache-control和etag控制缓存
现在的问题是:上述图标要是发生了改变,用户浏览器如何才能及时得到更新呢?
因为cache-control配置了一个很大的失效时间间隔,在用户本地存在缓存的情况下,浏览器是不会再次发起请求的
图片和样式文件的更改一般不会给网站带来灾难性的影响,但如果是js文件被修改但是用户浏览器依旧使用的是过期的缓存文件,这种情况相比较而言对网站的影响就要大得多。
如何避免此类问题呢?结合知乎个人头像的例子,不难想到的一种方案就是对修改的脚本文件添加一个修改的标志,类似下面这个样子
<script src="dir/test.js?modify=true"></script>
如果频繁修改呢,下面这种方式似乎给好一点
<script src="dir/test.js?version=2.0"></script>
上面的方案都是基于script标签的,在模块化大行其道的今天,脚本加载器应该是会考虑诸如此类实际问题的,例如在seajs中有下面的配置功能
seajs.config({ vars: { 'version': '2' } });
define(function(require, exports, mole) {
var lang = require('./dir/test.js?version={version}');
});
考虑一下现实吧,假设文件A在系统中很重要,因此存在大量文件引用,如果还采用上述的方案,这无疑是烦人的体力劳动,如何解脱呢?
总体的方案是:
下面给出stackoverflow上一个基于php的实现方案,原文在 这里
+ 首先,在apache的配置文件.htaccess中开启重写功能,并且添加规则
RewriteEngine on RewriteRule ^(.*)\.[\d]{10}\.(css|js)$ $1.$2 [L]
function auto_version($file){ if(strpos($file, '/') !== 0 || !file_exists($_SERVER['DOCUMENT_ROOT'] . $file)) return $file; $mtime = filemtime($_SERVER['DOCUMENT_ROOT'] . $file); return preg_replace('{\\.([ ^./]+)$}', ".$mtime.\$1", $file); }
<script href="<?php echo auto_version('/js/base.js'); ?> />