如何确保浏览器立即读取最新的静态文件

How to make sure the browser read the latest static files immediately

我在通过 CDN (aws cloudfront) 分发的 aws s3 上提供静态 webapp。这些文件是带有汇总的基于 ES6 的构建版本。简而言之,除了 index.html 汇总将在每次构建 webapp 时生成新的哈希文件。所以每次更新文件总是唯一的,除了index.html。然后在aws cloudfront上,我将index.html放入失效缓存列表中。

那么,我希望用户始终使用这种方法请求最新版本的 webapp。是的,它有效,但有一点注意!

所以一旦有新的更新,浏览器仍然在第一时间加载旧的index.html文件。我必须刷新页面才能推送浏览器获取最新的 index.html。这对最终用户不利。他们不想知道清爽,大多数人不会知道吧?

最后一个实验,我在 index.html 上添加了小脚本来执行版本验证,如下所示:

  <script>
    fetch('/version.json').then(r => {
      if (r.status == 200) {
        return r.json()
      } else {
        alert("Found server updated, let us resync the contents!")
        location.reload(true)
      }
    }).then(j => {
      if (window.localStorage.getItem("app-version")) {
        if (j.version != window.localStorage.getItem("app-version")) {
          alert("Found server updated, let us sync the contents!")
          window.localStorage.setItem("app-version", j.version)
          location.reload(true)
        }
      } else {
        window.localStorage.setItem("app-version", j.version)
      }
    })
  </script>

该脚本按预期工作,但想知道我是否会有更好的解决方案?请有其他想法,好吗?

预期行为

浏览器立即了解最新的 index.html,而无需来自最终用户的任何 refresh/reload 页面。

谢谢

只需在 URL 中使用时间戳即可强制浏览器获取最新版本。

(()=>{

  // Get the current timestamp
  var now = new Date().getTime();

  // Check for a ts parameter in the url (index.html?ts=2345234523)
  const urlParams = new URLSearchParams(location.search);
  var ts = urlParams.get('ts');

  // If there is no timestamp parameter,
  // or the timestamp parameter is older than 1 minute
  // redirect the page to the latest version
  if(!ts || now - ts > 60000){
     location.href = `index.html?ts=${now}`;
  }

})();

你会想把它放在顶部附近,这样你就不会在重定向之前加载很多东西。

我会利用 service-worker 来更轻松、更高效地加载 和缓存 应用程序的内聚版本。

Service Worker 有一个内置机制来检查应用程序是否已更新,每次启动应用程序时都会检查。

它不会做的是在应用 运行 时触发检查。虽然您可以定期轮询以检查更新,但让您的服务器和用户订阅更新会更有效,您可以使用 Firebase RTDB(实时数据库)之类的东西来做到这一点:

当您发布新版本并希望立即强制所有 运行 实例更新时,您可以更改它们订阅的版本或时间戳并触发服务工作者更新检查,然后刷新并重新加载应用程序。

有很多可用的模式可以提示用户任何更新,以防他们正在填写表格等...