首页 > 解决方案 > 如何强制加载当前版本的离线网络应用程序?

问题描述

我正在做一个小型的离线网络应用程序/PWA。它旨在从主屏幕图标打开并通过在离线时完全从缓存加载来模仿常规应用程序。

该应用程序是使用 Vue 编写的,为了完成上述任务,我只是使用他们的 PWA 模板及其生成的任何内容。据我所知,这是使用GenerateSW 插件设置工作箱来预缓存Webpack构建中的所有内容,并使用register-service-worker注册它。也就是说,我对细节几乎没有开箱即用的控制,这意味着它是一个交钥匙解决方案。

也就是说,我不确定如何在应用程序的新版本可用时实际加载它。以上可以检测到这一点 - 生成的带有我更改的 SW 注册文件如下所示:

import debug from 'debug';
import { register } from 'register-service-worker';


if (process.env.NODE_ENV === 'production') {
  register(`${process.env.BASE_URL}service-worker.js`, {
    ready(...args) {
      log('App is being served from cache by a service worker.\n', ...args);
    },
    cached(...args) {
      log('Content has been cached for offline use.', ...args);
    },
    updated(...args) {
      log('New content is available; please refresh.', ...args);
    },
    offline(...args) {
      log('No internet connection found. App is running in offline mode.', ...args);
    },
    error(error, ...args) {
      log('Error during service worker registration:', error, ...args);
    }
  });
}

当我新建应用程序并在浏览器中刷新应用程序时,将updated()执行回调,但没有执行任何其他操作。当我尝试添加:

window.location.reload(true);

这应该是强制刷新,我只是得到一个刷新循环。我假设这是因为服务工作者缓存完全独立于浏览器缓存,并且不受上述或Ctrl+之类的影响F5。(这使得“请刷新”颇具误导性。)

由于这将模拟一个原生应用程序,并且它应该是一个简单的业务线工具,我真的不需要做任何比在更新可用时立即重新加载到应用程序的新版本更复杂的事情. 我怎样才能做到这一点?

标签: cachingwebpackservice-workerprogressive-web-appsworkbox

解决方案


好的,所以我观察到的行为是更新确实自动发生,只是事件的确切顺序并不明显。我将尝试描述我对生成的 Service Worker 如何在已安装的 PWA 场景中工作的最佳理解。为简单起见,我会用“应用程序版本”来说话,因为这背后的心智模型更接近应用程序的工作方式,而不是网页的工作方式:

  • 您将应用程序的 v1 部署到服务器,在设备上安装/预缓存它,然后首次运行它。
  • 当您暂停和恢复您的应用程序时,它根本不会访问您的服务器。
  • 该应用程序将在冷启动或您重新加载页面时检查更新,即在 Android 上使用下拉手势。
    (可能还会定期因为缓存的版本过时,但我还没有检查过。)
  • 假设您同时部署了应用程序的 v2。重新加载应用程序的 v1 实例将找到此更新,并预缓存它。
    (提示用户重新加载的一个原因似乎没有意义。无论重新加载的目的是什么,都已经发生了。)
  • 再次重新加载v1 的实例绝对没有任何作用。该应用程序在重新加载之间保持运行,之后您将获得 v1。
    (为什么提示用户重新加载的第二个原因是没有意义的 - 这不是导致新版本应用程序加载的原因。)
  • 但是,下次您冷启动您的应用程序时 - 例如,从任务切换器中删除它并重新打开 - 您的应用程序的 v2 将被加载,我猜 v1 将被清除。也就是说,您的应用程序必须完全关闭才能加载更新。

简而言之,要将应用程序从 v1 更新到 v2,需要执行以下步骤:

  1. 将 v2 部署到服务器
  2. 刷新设备上的 v1 实例,或关闭并重新打开应用程序。
  3. 关闭并重新打开应用程序(再次)。

推荐阅读