使用CakePHP处理图像缓存(和资产压缩)

使用CakePHP处理图像缓存(和资产压缩),cakephp,caching,Cakephp,Caching,来自雅虎s文件: Expires标头最常用于图像,但它们应该是 用于所有组件,包括脚本、样式表和Flash 组成部分 我使用“mod_expires”Apache模块遵循上述建议。我的实现很像HTML5样板文件。看 这是同一个雅虎的另一句话!文件: 请记住,如果您使用远未来过期标头,则必须 每当组件发生更改时,请更改组件的文件名。在 雅虎!我们通常将此步骤作为构建过程的一部分:版本 例如,数字嵌入在组件的文件名中, 雅虎2.0.6.js 我已经用MarkStory的插件处理了CSS和JavaSc

来自雅虎s文件:

Expires标头最常用于图像,但它们应该是 用于所有组件,包括脚本、样式表和Flash 组成部分

我使用“mod_expires”Apache模块遵循上述建议。我的实现很像HTML5样板文件。看

这是同一个雅虎的另一句话!文件:

请记住,如果您使用远未来过期标头,则必须 每当组件发生更改时,请更改组件的文件名。在 雅虎!我们通常将此步骤作为构建过程的一部分:版本 例如,数字嵌入在组件的文件名中, 雅虎2.0.6.js

我已经用MarkStory的插件处理了CSS和JavaScript文件。这只是让Asset Compress的shell成为构建过程的一部分的问题

我遇到的两个问题都与图像有关:

我在我的网站上有常规的
标签,还有CSS
背景图像。对于这两种类型的图像,我目前都没有一种优雅的处理缓存破坏的方法。对于
标记,我的“core.php”文件中有一行:

<>虽然这确实提供了一种自动处理<代码> >代码>标签的高速缓存崩溃的方法(如果标签是使用<代码> $ $-HTML>图像(…)<代码> >,我不认为这是优雅的,原因有两个:

  • 它使用一个查询字符串,即
  • 每次访问特定视图时,都会检查图像的时间戳。是的,您可以缓存视图,但是您可能希望在视图的缓存版本过期之前更新该视图中的图像,因此您必须做任何必要的操作来触发该视图被重新缓存,而我认为这是不优雅的。
  • 至于处理CSS
    background image
    s的缓存破坏,我必须手动更新LESS文件。绝对不优雅

    使用CakePHP和/或资产压缩应该如何处理图像缓存?

    缓存失效、性能和web 人们普遍认为编程中最难做的事情之一是。然而,对于资产(js文件、css文件、图像等),这并不是真的。为web资产提供服务的最佳逻辑是:

    • 服务期为(1年)
    • 如果资产发生更改,请更改url
    然而,当应用到web时,有一个复杂的问题

    考虑对
    /css/main.css
    的请求,其中包含:

    body {
        background-image:url('../img/bar.gif');
    }
    
    显然,这将在加载css文件时触发对
    /img/bar.gif
    的请求。假设图像带有适当的标题,则只有两种方法可以加载更新版本的
    bar.gif

    • 更改css文件的内容
    • 更改css文件所在的文件夹
    第一个是有问题的,如果它不是自动化的(即使是自动化的,也可能出错),第二个很容易

    版本前缀资源URL->不再出现问题 解决css/js/文件问题的一个简单方法是将构建编号作为url的一部分:

    /v123/css/foo.css
     ^
    
    您可以通过修改app helper webroot函数来完成此操作,例如:

    public function webroot($file) {
        $file = parent::webroot($file);
        if (Configure::read('debug')) {
            return $file;
        }
    
        return '/' . Configure::read('App.version') . $file;
    }
    
    顺便说一句,使用cdn也是同样的技术——这可能是提高前端性能的最好方法

    通过这种方式,当您升级站点版本时,所有资产都会获得新的URL。请注意,使用此技术,所有引用的资产都需要使用相对URL,而不是绝对URL:

    .foo {
        /* background-image:url('/img/bar.gif'); // won't work */
        background-image:url('../img/bar.gif');
    }
    
    否则,对css文件的请求是特定于应用程序版本的,但引用的图像不是,即使使用新的应用程序版本,也会从浏览器缓存(如果相关)中读取

    实现相同的结果,不更改文件系统 如果不想更改文件夹结构,可以使用重写规则来破坏文件名缓存:

    <IfModule mod_rewrite.c>
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteRule ^/v\d+/(css|files|js)/(.+)$ /$1/$2 [L]
    </IfModule>
    
    app
        webroot
            css
                img <- css assets only
            fonts
            img
            js
    
    您可以为css、字体和js请求添加版本前缀;间接地对css图像执行相同的操作(假设它们使用
    背景图像:url('img/bar.gif');
    )形式的相对url,而不将相同的逻辑应用于其他资产(用户化身、其上传的cat视频等)

    或者对所有图像使用数据URI 谷歌就是这样做的


    最终,它变成了一个选择,一个是您希望构建过程有多复杂,另一个是为了获得什么真正的好处。很多用户,因此对于随机用户来说,应用程序的缓存逻辑很可能只适用于他们当前的访问-这是一次性终止整个资产缓存不是件坏事的主要原因之一。

    谢谢,但我不能说我是第一种方法的忠实粉丝,因为更改一个图像会使用户对所有资产的缓存失效。至于重写规则,我以前使用过,但我不相信CakePHP有一种内置的方法来处理这个问题。你不需要重写吗?这仍然需要每次检查图像的时间戳。在我看来,它就像两个:一个是在资产路径之前有一个/v[#####]/path(这会导致在只有一个更改时所有资产都被重新下载),另一个是将请求(如
    /css/style.12345.css
    路由到
    /css/style.css
    (您提供的链接)。我不知道这两件事如何一起成为一种方法。哦,我现在明白你的意思了。感谢你的澄清!我感谢你的时间,也感谢你提供了一个解决方案,但我认为改变一项资产会导致所有资产重新下载这一事实是一个破坏交易的因素,至少对我来说是这样。我觉得奇怪的是kePHP拥有大量的功能,无法(优雅地)处理这样的基本需求,或者至少无法由核心开发人员使用插件来处理。我通读了你的更新答案。非常感谢!+1。它有很好的信息,并提供了多种策略
    app
        webroot
            css
                img <- css assets only
            fonts
            img
            js