在apache中控制更改js和css文件的浏览器缓存的最佳方法是什么?

时间:2016-01-07 20:44:35

标签: javascript css caching apache2

我们刚刚对网站进行了重新设计,在部署之后,我们不得不对控制新外观的各种css和javascript文件进行一些小的调整。我们遇到的一个问题是浏览器似乎缓存了这些文件,因此用户客户端可能看不到我们做的一些修复。
我们最初想过用文件的mtime做一些事情并且作为一个快速解决方案&#39; hack,我们使用url参数修改了对这些文件的一些主要调用,该参数使用服务器端php附加有问题的文件的最新mtime。但是这并没有按计划运行,因为我们的部署系统克隆了一个git分支,因此,每个部署最终都会触及每个文件并改变其mtime。 (最终结果是,部署一个小修补程序最终会告诉客户端浏览器重新加载每个<LINK><Script>标记,以便在部署之后修改文件内容是否实际更改了。)

我正在查看apache FileETag,但它似乎使用了mtime,size和inode。 (我希望找到类似校验和的东西)mtime显然不能使用我们使用的部署方法,如果更改不改变文件的长度,大小可能不会改变。我不熟悉inode信息的工作方式,因此我不确定这是否符合我们的需求。

所以我想知道是否还有其他建议会告诉客户浏览器只有在文件内容实际发生变化时才重新加载文件。

3 个答案:

答案 0 :(得分:4)

因此,人们经常会混淆缓存的两个重要区别:

  1. 浏览器应该缓存资源多长时间。这通常由Cache-Control标头驱动(尽管旧的Expires标头有时仍然使用)。在此资源被视为旧资源之前,不会向服务器发出请求。这是您想要的,因为它可以节省带宽和延迟带来的问题。

  2. 重新验证过期资源应该怎么做。这是从Last-Modified或ETag标题驱动的。这里向服务器发出了 请求,服务器返回304响应,说明&#34;我没有根据最后修改过的文件向您发送该文件的新版本。您给我的ETag详细信息,您仍然拥有的副本仍然是最新版本,所以请考虑另外一点&#34;。这实际上仅对大型资源(例如大图像或视频)有用。 CSS和JS文件通常较小,下载它们的时间并不比发送304响应多得多,所以你在这里使用304并没有那么多。从服务器(无论是304还是资源本身)返回任何响应的延迟是主要瓶颈,只能通过将文件保留在缓存中来避免更长时间。

  3. 你似乎想要使用一些验证技术(修改时间或ETag)给你提供良好的缓存但是当你改变一些东西时立即重新加载但这不是最好的方法,因为你基本上只能使用上面的第二部分当它是第一个给你带来好处的时候。关于为什么延迟是btw问题的好文章:http://www.nateberkopec.com/2015/11/05/page-weight-doesnt-matter.html。该文章中有很多其他好的信息,所以建议阅读全部内容。

    因此,您最终需要非常长的缓存控件,因此在第一次下载后它会保留在缓存中。但是,当您更改内容时,您希望强制用户尽快重新加载。那些是相反的要求。

    所以你的选择是要么使用缓存破坏技术,要么基本上忽略了这个问题。

    缓存破坏技术基本上欺骗了浏览器认为它要求不同的资源。例如,向URL添加参数。 CSS技巧在这里有很多关于各种技术的页面:https://css-tricks.com/strategies-for-cache-busting-css/。基于您的部署技术,它不会在mtime上工作,因此您确实需要在此处添加版本号,但这有多容易取决于您创建页面的方式以及您使用的构建过程。

    另一种选择是在资源过期之前忽略该问题。这可能看起来很奇怪,但越来越多我的首选方案,所以让我解释一下原因。我所做的是为可能发生变化的关键资源(例如HTML,CSS和JS)设置一个非常的到期时间。说一个小时或3.然后接受人们将获得缓存的,可能过时的资源。大多数建议是针对到期时间,希望暂时缓存您的网页,但考虑到缓存并不像某些人认为的那样大(再次见the article referenced above)除了非常频繁的访客外,大多数人都没有看到恕我直言。因此,您没有长期到期的麻烦,没有任何好处。使用短期到期有几个好处:

    • 没有复杂的缓存破坏
    • 除非访问者最近访问过,否则在缓存到期时间内,他们将获得最新资源。
    • 您现在也可以缓存静态页面。大多数缓存清除技术依赖于每次下载的HTML(因此您可以检查是否已在页面需要的资源上使用任何缓存清除技术),但是如果浏览到主页,则浏览另一个页面,然后多次返回主页那么每次下载主页都毫无意义!为什么不在浏览时缓存它并具有即时响应性?除非你是一个新闻网站,否则老主页很可能会在99%的时间内获得服务。使用short expiries可以缓存HTML页面。
    • 每次初次访问可能会比较慢,但一旦这样就会缓解资源并快速浏览(假设页面共享大量资源)。现在最初的页面加载非常重要 - 不要误解我的意思,但是考虑到缓存大小,无论如何,这可能会产生额外的负面影响,并且您的资源很可能已被强制退出缓存。

    缺点是:

    • 在发布期间,网站上的网页可能会中断。例如,他们访问主页并下载CSS,然后您使用新的HTML和CSS发布所有页面,然后相同的访问者查看另一个页面,因此获取新的HTML但仍使用缓存的旧CSS。这是多大的交易让你自己决定。个人对于大的改变,我的版本控制我的CSS文件(stylesv2.css),但对于调整,我只是忍受这个。很少会导致问题,并且用户经常在看起来错误时重新加载页面。显然,对于某些可能有点简单的网站而言,这可能不是一种选择。
    • 所有表现工具(例如Google的网页见解)都会标记您有短期到期 - 即使您已经明确做出了这个选择 - 因为他们(我认为不正确)认为有很长的期限总是更好。更令人烦恼的是。

    由于执行不佳,ETag在我看来毫无用处。默认情况下,Apache使用文件大小和修改时间的组合 - 正如您正确指出的那样,可能无法识别文件内容是否已更改。 Inode基本上是磁盘上的文件引用,因此类似。在使用负载均衡器和多个Web服务器时也不建议这样做,因为inode在每个服务器中都会有所不同(这就是为什么它不再默认使用)。内容的散列会更好(尽管可能更慢)。但Etags在Apache上的主要问题是当你gzip你的数据时你不会工作(你应该这样做)!请在此处查看我的博客文章:https://www.tunetheweb.com/performance/http-performance-headers/etag/。因此,您不应该在Apache上使用Etags。而且如上所述,它们对于小资源(如您希望压缩的文本资源)也相当无用。最后修改几乎同样好,并且没有gzip资源的错误。

    正确的缓存是您可以对网站进行的最大性能改进之一。没有它,当您浏览它时,无论您的服务器或访问者计算机有多快,网站都会感到缓慢而且迟钝。有了它,即使使用慢速服务器,网站也能感受到快速响应。然而,当你注意到这一点时,它确实会使事情变得复杂,因此需要对如何正确设置它进行一些思考。

    我在这里详细介绍了如何为它配置Apache:https://www.tunetheweb.com/performance/http-performance-headers/caching/

    希望有所帮助 - 即使它有点长时间啰嗦,但遗憾的是并没有给你快速解决方案,你无疑在寻找!

答案 1 :(得分:1)

如果你有gulp.js,请使用gulp-cache-bust或使用gulp-change chnage version代码:

gulpfile.js:

    function performChange(content) {
    var t = new Date().getTime();
    return content.replace(/v=\d+/g, 'v=' + t);
    }

    gulp.task('change', function () {
        return gulp.src('index.html')
            .pipe(change(performChange))
            .pipe(gulp.dest(''))
    });

html标签:

<link href="Content/styles.min.css?v=1508576413811" rel="stylesheet" />
<script src="Scripts/build.js?v=1508576413811"></script>

答案 2 :(得分:0)

如果您的应用程序有版本号,那么您可以将其构建到文件名中,并在服务器上使用某种过滤器来删除版本号并提供文件。

实施例: [...] location ~ \.php$ { fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; include fastcgi_params; } [...] /main_v1.css

这会阻止缓存。

作为替代方法,您可以尝试向请求添加查询字符串参数。我听说不太可能在某些浏览器上工作。

实施例: /main_v2.css /main.css?v=1