不重新获取已过期的缓存文件

问题描述 投票:3回答:3

我有一个React应用(无CRA),在parcel-bundler的帮助下使用代码拆分。

[当我在我的应用中单击时,它将提取一次我的每个js文件,并将它们缓存在浏览器中,基本上是在标头中注入脚本标签。因此,当我转到用户页面时,这将注入到我的index.html标头中:

<script async="" type="text/javascript" charset="utf-8" src="http://localhost:1234/Users.3ab12f6b.js"></script>

这很好。我的问题是,当用户正在浏览并且我在服务器上部署了新版本的应用程序时,已经打开的浏览器将永远不会获得这些文件,除非关闭并在新选项卡上重新打开它。我尝试在index.html中设置<meta http-equiv="Cache-Control" content="max-age=10 no-cache">只是为了尝试它是否确实可以工作,但似乎什么也没做。

我的服务器正在发回Cache-Control public, max-age=0,以及ETag和Last-Modified。不过,由于文件已缓存在我的html文档中,因此似乎不再有任何请求到达服务器来检查这些文件是否已过期。

我真的再也没有线索了。我在这里缺少基本的东西吗?

javascript reactjs nginx caching parcel
3个回答
2
投票

首先有几个端点,它是周期性地调用返回最新版本的端点,如果react-app的早期版本不匹配,则window.location.reload(true)以重新加载浏览器而不考虑缓存。”因此,当我遇到这种情况时,开发人员将使用最新的提交ID更新文件,我们将在版本端点的响应中返回此文件当不匹配时,SPA将执行其余操作。

第二种选择是使用服务人员,因为它可以更优雅地处理它有多个示例正在在下面添加对它们的引用,而未添加整个示例,那么它将使此答案TLDR

我下面显示的示例脚本取自基本create-react-app的service worker文件。

function registerValidSW(swUrl, config) {
  navigator.serviceWorker
    .register(swUrl)
    .then(registration => {
      registration.onupdatefound = () => {
        const installingWorker = registration.installing;
        if (installingWorker == null) {
          return;
        }
        installingWorker.onstatechange = () => {
          if (installingWorker.state === 'installed') {
            if (navigator.serviceWorker.controller) {
              // At this point, the updated precached content has been fetched,
              // but the previous service worker will still serve the older
              // content until all client tabs are closed.
              console.log(
                'New content is available and will be used when all ' +
                  'tabs for this page are closed. 
              );

              // Execute callback
              if (config && config.onUpdate) {
                config.onUpdate(registration);
              }
            } else {
              // At this point, everything has been precached.
              // It's the perfect time to display a
              // "Content is cached for offline use." message.
              console.log('Content is cached for offline use.');

              // Execute callback
              if (config && config.onSuccess) {
                config.onSuccess(registration);
              }
            }
          }
        };
      };
    })
    .catch(error => {
      console.error('Error during service worker registration:', error);
    });
}`

当您进入此检查内部时,更新已准备就绪

  `               `if (navigator.serviceWorker.controller) {`

这是您执行强制重新加载的逻辑

示例1:-https://zach.codes/handling-client-side-app-updates-with-service-workers/

示例2:-https://medium.com/@kellyrmilligan/create-react-app-let-your-users-know-when-the-app-has-been-updated-with-a-notification-21335d85481c


1
投票

替代解决方案之一是,对于每个Web应用程序,我们编写一些api调用以在应用程序中显示一些动态内容。

在该api调用中,您需要将构建版本ID作为响应之一作为参数传递。

第一次在前端加载时,将构建版本存储在localStorage或cookie中。在下一次调用或其他api调用之后,检查先前的构建版本(即,来自localStorage的构建版本)是否等于服务器api调用中的最新构建版本。

如果两者相同,则意味着无需重新获取或刷新页面。

如果构建版本不同,则需要创建一个前端函数来重新加载该函数。

简短:创建一个全局函数(例如:function checkBuild(buildVersion)以从每个api调用响应中获取构建版本,并对其进行检入并刷新页面。

希望有帮助。


0
投票

我的网站上确实有这个问题。有两种解决问题的好方法。我可以给您2个我熟悉的选项:

1)部署应用程序后,请使用套接字将消息发送到浏览器,并在事件有效负载中添加新的脚本URL。然后您可以在浏览器中更改本地脚本路径或重新加载页面以获取新的页面。

2)创建一个每隔几分钟执行一次Ajax请求以测试较新版本的服务工作者。找到新版本后,将带有该URL的消息发布到浏览器,并执行与选项1相同的操作。

我希望这是您要寻找的东西。

© www.soinside.com 2019 - 2024. All rights reserved.