防止过时的 CSS 和 JavaScript 的最佳实践是啥

Posted

技术标签:

【中文标题】防止过时的 CSS 和 JavaScript 的最佳实践是啥【英文标题】:What are best practices for preventing stale CSS and JavaScript防止过时的 CSS 和 JavaScript 的最佳实践是什么 【发布时间】:2010-09-26 06:33:38 【问题描述】:

我正在为一个项目研究这个问题,我想知道其他人正在做什么来防止每个新版本都提供陈旧的 CSS 和 javascript 文件。我不想附加时间戳或类似的东西,这可能会阻止对每个请求进行缓存。

我正在使用 Spring 2.5 MVC 框架,并且我已经在使用 google api 来提供原型和脚本。我还在考虑使用 Amazon S3 和新的 Cloudfront 产品来最大程度地减少网络延迟。

【问题讨论】:

【参考方案1】:

我在请求中添加了一个带有修订号的参数,例如:

<script type="text/javascript" src="/path/to/script.js?ver=456"></script>

'ver' 参数在每次构建时自动更新(从构建更新的文件中读取)。这样可以确保仅针对当前版本缓存脚本。

【讨论】:

最好的解决方案是最简单的 :) 谢谢 许多旧代理会拒绝缓存任何带有查询字符串的内容。最好使用某种捆绑器将该 id 用于您的文件名。 /path/to/script-456.js 好多了。更容易使用,/path/to/v456/script.js【参考方案2】:

与@eran-galperin 一样,我在对 JS 文件的引用中使用了一个参数,但我包含了一个服务器生成的对文件“最后修改”日期的引用。 @stein-g-strindhaug 建议使用这种方法。它看起来像这样:

<script type="text/javascript" src="/path/to/script.js?1347486578"></script>

服务器忽略静态文件的参数,客户端可能会缓存脚本,直到日期代码更改。如果(且仅当)您修改服务器上的 JS 文件,日期代码将自动更改。

例如,在 php 中,我创建此代码的脚本如下所示:

function cachePreventCode($filename) 
    if (!file_exists($filename))
        return "";
    $mtime = filemtime($filename);
    return $mtime;

因此,当您的 PHP 文件包含对 CSS 文件的引用时,它可能如下所示:

<link rel="stylesheet" type="text/css" href="main.css?<?= cachePreventCode("main.css") ?>" />

...这将创建...

<link rel="stylesheet" type="text/css" href="main.css?1347489244" />

【讨论】:

【参考方案3】:

关于缓存文件,我还没有遇到过使用查询字符串方法与过时缓存文件相关的错误问题。

但是,关于性能,并回应 Todd B 提到的按文件名加速,请查看 Steve Souders 的工作以了解有关该主题的更多信息:

“Squid 是一种流行的代理,它不会使用查询字符串来缓存资源。当代理缓存后面的多个用户请求同一个文件时,这会损害性能 - 而不是使用每个人都必须发送请求的缓存版本到源服务器。”

“代理管理员可以更改配置以支持使用查询字符串缓存资源,只要缓存标头表明这是合适的。但默认配置是 Web 开发人员最常遇到的。”

http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/

【讨论】:

【参考方案4】:

使用带有If-Modified-Since 标头的conditional get 请求

【讨论】:

【参考方案5】:

这实际上是一个非常困难的问题,您可以花一些时间设计正确的解决方案。

我建议使用 url 中内置的时间戳和/或版本来发布您的文件,而不是:

/media/js/my.js 你最终会得到:

/media/js/v12/my.js 或类似的东西。

您可以使用任何工具自动执行版本控制/时间戳。

这具有在推出新版本时不会破坏网站的额外好处,并允许您进行真正的并行测试(与仅剥离版本并发回最新文件的重写规则不同)。

使用 JS 或 CSS 需要注意的一件事是,当您在其中包含依赖 url(背景图片等)时,您需要确保 JS/CSS 时间戳/版本在内部资源发生变化时发生变化(以及重写它们,但可以通过非常简单的正则表达式和资源清单来实现)。

无论您做什么,请确保不要在最后扔一个 ?vblah,因为当您这样做时,您基本上会将缓存扔出窗口(不幸的是,这是迄今为止处理此问题的最简单方法)

【讨论】:

【参考方案6】:

如果您获得文件的“修改时间”作为时间戳,它将被缓存,直到文件被修改。只需使用辅助函数(或在其他框架中调用的任何函数)来添加从文件中获取时间戳的 script/css/image 标签。在类似 unix 的系统(大多数幸存者都是)上,您可以简单地 touch 文件强制修改时间在必要时进行更改。

Ruby on Rails 在生产模式下使用这种策略(默认情况下我会离开),并在开发模式下使用普通时间戳(以确保没有缓存某些内容)。

【讨论】:

【参考方案7】:

如果你使用 MAVEN,你可以使用这个,在你的 pom.xml 中添加:

<properties>
   <maven.build.timestamp.format>yyyyMMddHHmm</maven.build.timestamp.format>
   <timestamp>$maven.build.timestamp</timestamp>
</properties>

有了这个,你可以在你的视图中访问 $timestamp。 喜欢这个示例:

<script type="text/javascript" src="/js/myScript.js?t=$timestamp"></script>

【讨论】:

以上是关于防止过时的 CSS 和 JavaScript 的最佳实践是啥的主要内容,如果未能解决你的问题,请参考以下文章

使用jQuery防止过时的Ajax数据

JavaScript实现Tab标签页切换的最简便方式

现代浏览器中的非阻塞 javascript 和 css。还需要吗?

6种编写HTML和CSS的最有效的方法

如何防止用户生成的 HTML 中的 Javascript 注入攻击

jQuery——过时,但是经典,关注核心点即可。