我应该在我的 HTML 中输入什么来确保用户获得我页面的最新版本,而不是旧版本?

What do I put in my HTML to ensure users get latest version of my page, not old version?

我有一个主要是静态的 HTML 网站,由 CDN 提供服务(加上一些 AJAX 到服务器),并且希望用户的浏览器缓存所有内容,直到我更新任何文件然后我希望用户的浏览器获得新版本。

对于我网站上所有类型的静态文件(HTML、JS、CSS、图像等),我该如何实现? (HTML 或其他地方的设置)。显然我可以告诉 CDN 使它的缓存过期,所以它是我正在考虑的客户端。

谢谢。

为了在客户端实现你想要的,你必须在 HTML 中加载它们时更改静态文件的 url,即更改文件名,添加随机查询字符串,如 unicorn.css?p=1234,等等。一个简单的自动化方法是使用任务运行器,如 Gulp and have a look at this package gulp-rev.

简而言之,如果您将 gulp-rev 集成到 Gulp 任务中,它会自动将内容哈希附加到通过管道传输到任务流中的所有静态文件并生成 JSON清单文件,它将旧文件映射到新重命名的文件。所以像 unicorn.css 这样的文件将变成 unicorn-d41d8cd98f.css。然后您可以编写另一个 Gulp 任务来爬取您的 HTML/JS/CSS 文件并替换所有 url 或使用此包 gulp-rev-replace.

应该有很多在线教程向您展示如何完成此操作。如果您使用 Yeoman, you can check out this static webapp generator I wrote here,其中包含一个 Gulp 例程。

实现此目的的一种方法是使用 HTTP Last-ModifiedETag headers。在服务文件的 HTTP headers 中,服务器将发送页面最后修改的日期(在 Last-Modified header 中),或代表当前状态的随机 ID页面的 (ETag),或两者:

HTTP/1.1 200 OK
Content-Type: text/html
Last-Modified: Fri, 18 Dec 2015 08:24:52 GMT
ETag: "208f11-52727df9c7751"
Cache-Control: must-revalidate

如果 header Cache-Control 设置为 must-revalidate,它会导致浏览器缓存页面以及 Last-ModifiedETag headers 它收到了。在下一个请求中,它将以 If-Modified-SinceIf-None-Match:

的形式发送它们
GET / HTTP/1.1
Host: example.com
If-None-Match: "208f11-52727df9c7751"
If-Modified-Since: Fri, 18 Dec 2015 08:24:52 GMT

如果页面的当前 ETag 与来自浏览器的页面匹配,或者如果页面自浏览器发送之日起未被修改,而不是发送页面,服务器将发送一个 Not Modified header 和一个空的 body:

HTTP/1.1 304 Not Modified

请注意,只有两种机制(ETagLast-Modified)中的一种是必需的,它们都可以独立工作。

这样做的缺点是无论如何都必须发送请求,因此性能优势主要针对包含大量数据的页面,但特别是在具有高延迟的 Internet 连接上,页面仍然需要长时间加载。 (不过它肯定会减少您的流量。)

Apache 自动 generates an ETag(使用文件的索引节点号、修改时间和大小)和一个 Last-Modified header(基于文件的修改时间)用于静态文件.我不知道其他 web-servers,但我认为它会相似。对于动态页面,您可以自己设置header(例如将内容的MD5和发送为ETag)。

默认情况下,Apache 不发送 Cache-Control header(默认为 Cache-Control: private)。此示例 .htaccess 文件使 Apache 为所有 .html 文件发送 header:

<FilesMatch "\.html$">
    Header set Cache-Control "must-revalidate"
</FilesMatch>

另一种机制是通过发送 Cache-Control: public 让浏览器缓存页面,但要动态改变 URL,例如通过将文件的修改时间附加为查询字符串 ( ?12345)。这只有在您的 page/file 仅从您的 Web 应用程序内部链接时才是真正可能的,在这种情况下,您可以动态生成指向它的链接。例如,在 PHP 中你可以这样做:

<script src="script.js?<?php echo filemtime("script.js"); ?>"></script>

这就是 HTML5 Application Cache 为您所做的。将所有静态内容放入缓存清单中,它将缓存在浏览器中,直到更改清单文件为止。作为一个额外的好处,即使浏览器处于离线状态,静态内容也将可用。

您的 HTML 的唯一变化是在 <head> 标签中:

<!DOCTYPE HTML>
<html manifest="cache.appcache">
...
</html>