摘自Yahoo! 加快网站最佳实践文档:
Expires标头最常与图像一起使用,但应在所有组件(包括脚本,样式表和Flash组件)上使用它们。
我使用“ mod_expires” Apache模块遵循上述建议。我的实现与HTML5 Boilerplate的实现非常相似。请参阅此.htaccess代码。
这是来自同一Yahoo!的另一个报价!文献:
请记住,如果使用远期的Expires标头,则每当组件更改时,都必须更改组件的文件名。在雅虎!我们通常将此步骤作为构建过程的一部分:版本号嵌入在组件的文件名中,例如yahoo_2.0.6.js。
我已经使用Mark Story的Asset Compress插件通过CSS和JavaScript文件来处理此问题。只需将Asset Compress的shell纳入构建过程即可。
现在针对我遇到的两个问题,它们都与图像有关:
我<img>在整个网站上都有常规标签,也有CSS background-image。我目前还没有一种优雅的方式来处理这两种类型的图像的缓存清除。对于<img>标签,我的“ core.php”文件中包含以下行:
Configure::write('Asset.timestamp', 'force');
Run Code Online (Sandbox Code Playgroud)
尽管这确实提供了一种自动处理<img>标记的缓存清除的方法(前提是使用生成标记$this->Html->image(...)),但出于以下两个原因,我认为这种方法并不优雅:
至于处理CSS background-image的缓存破坏,我必须手动更新LESS文件。绝对不优雅。
如何使用CakePHP和/或Asset Compress处理图像缓存?
人们普遍认为,编程中最难做的事情之一就是缓存失效。然而,对于资源(js 文件、css 文件、图像等)来说,提供 Web 资源的最佳逻辑并不是真正的:
然而,当应用于网络时,会出现一个复杂的情况。
考虑 的请求/css/main.css,包含:
body {
background-image:url('../img/bar.gif');
}
Run Code Online (Sandbox Code Playgroud)
/img/bar.gif显然,这将在加载 css 文件时触发请求。假设图像带有适当的标头,则只有两种方法可以加载更新版本bar.gif:
如果不是自动化的话,第一个就会有问题(即使是自动化,也可能会出错),第二个很容易。
解决 css/js/files 问题的一种简单方法是将构建号作为 url 的一部分:
/v123/css/foo.css
^
Run Code Online (Sandbox Code Playgroud)
您可以通过修改应用程序助手 webroot 函数来完成此操作,例如:
public function webroot($file) {
$file = parent::webroot($file);
if (Configure::read('debug')) {
return $file;
}
return '/' . Configure::read('App.version') . $file;
}
Run Code Online (Sandbox Code Playgroud)
顺便说一句,使用 CDN 的技术是相同的——这可能是提高前端性能所能做的最好的事情。
这样,当您升级网站版本时,所有资产都会获得新的 url。请注意,使用此技术时,所有引用的资源都需要使用相对 URL,而不是绝对 URL:
.foo {
/* background-image:url('/img/bar.gif'); // won't work */
background-image:url('../img/bar.gif');
}
Run Code Online (Sandbox Code Playgroud)
否则,对 css 文件的请求是特定于应用程序版本的,但引用的图像不是特定于应用程序版本的,并且即使使用新的应用程序版本,也会从浏览器缓存(如果相关)中读取图像。
如果您不想更改文件夹结构,可以使用类似于 h5bp 中的重写规则来进行文件名缓存清除:
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/v\d+/(css|files|js)/(.+)$ /$1/$2 [L]
</IfModule>
Run Code Online (Sandbox Code Playgroud)
这意味着该 url提供请求时/v123/css/main.css的内容。/css/main.css
你在评论中提到
我认为更改一项资产会导致重新下载所有资产这一事实是一个破坏性的因素
除非您每分钟发布一个新的生产版本 - 这不会成为问题(除非您有 GB 的缓存内容,在这种情况下..您会遇到不同的问题)。拥有特定于文件的高性能缓存逻辑的唯一方法是将站点中的每个文件存储为文件内容的 sha1 - 应用于 css 文件,这意味着替换../img/foo.gif为../img/<hash of foo.gif's contents>.gif.
没有什么可以阻止使用多种技术,例如使用以下结构:
app
webroot
css
img <- css assets only
fonts
img
js
Run Code Online (Sandbox Code Playgroud)
您可以为您的 css、字体和 js 请求添加版本前缀;间接对 css-images 执行相同的操作(假设它们使用表单的相对 url background-image:url('img/bar.gif');),而不对其他资产(用户头像、他们上传的猫视频等)应用相同的逻辑。
这就是谷歌所做的=)。
最终,您需要在构建过程的复杂程度和真正的好处之间做出选择。许多用户的浏览器缓存为空,因此对于随机用户来说,应用程序的缓存逻辑很可能仅适用于他们当前的访问 - 这就是为什么一次性使整个资产缓存过期并不是一件坏事的主要原因之一事物。