在缓存优先服务辅助角色上加载后刷新页面



我目前正在考虑将服务工作者添加到我正在构建的 Web 应用程序中。

这个应用程序本质上是一个集合管理器。您可以对各种类型的 CRUD 项目进行,它们通常紧密地链接在一起(例如,A 有很多 B 有很多 C(。

sw-toolbox提供了一个toolbox.fastest处理程序,它进入缓存,然后进入网络(在99%的情况下,缓存会更快(,在后台更新缓存。我想知道的是,如何通知您有新版本的页面可用。我的目的是显示缓存的版本,然后,如果网络获取有更新的版本,则建议用户刷新页面以查看最新的编辑。不久前,我在YouTube视频中看到了一些东西,但主持人没有给出如何处理这个问题的线索。

这可能吗?是否有一些事件处理程序或承诺可以绑定到请求,以便我知道何时检索较新版本?然后,我会在页面上发布一条消息以显示通知。

如果没有,我知道我可以使用toolbox.networkFirst和合理的超时来使页面即使在 Lie-Fi 上可用,但它没有那么好。

我偶然发现了Mozilla Service Worker Cookbook,其中或多或少包含了我想要的东西:https://serviceworke.rs/strategy-cache-update-and-refresh.html

以下是相关部分(不是我的代码:为方便起见,此处复制(。

工作人员的提取方法

// On fetch, use cache but update the entry with the latest contents from the server.
self.addEventListener('fetch', function(evt) {
  console.log('The service worker is serving the asset.');
  // You can use respondWith() to answer ASAP…
  evt.respondWith(fromCache(evt.request));
  // ...and waitUntil() to prevent the worker to be killed until the cache is updated.
  evt.waitUntil(
    update(evt.request)
    // Finally, send a message to the client to inform it about the resource is up to date.
    .then(refresh)
  );
});
// Open the cache where the assets were stored and search for the requested resource. Notice that in case of no matching, the promise still resolves but it does with undefined as value.
function fromCache(request) {
  return caches.open(CACHE).then(function (cache) {
    return cache.match(request);
  });
}
// Update consists in opening the cache, performing a network request and storing the new response data.
function update(request) {
  return caches.open(CACHE).then(function (cache) {
    return fetch(request).then(function (response) {
      return cache.put(request, response.clone()).then(function () {
        return response;
      });
    });
  });
}
// Sends a message to the clients.
function refresh(response) {
  return self.clients.matchAll().then(function (clients) {
    clients.forEach(function (client) {
    // Encode which resource has been updated. By including the ETag the client can check if the content has changed.
      var message = {
        type: 'refresh',
        url: response.url,
        // Notice not all servers return the ETag header. If this is not provided you should use other cache headers or rely on your own means to check if the content has changed.
        eTag: response.headers.get('ETag')
      };
      // Tell the client about the update.
      client.postMessage(JSON.stringify(message));
    });
  });
}

处理"资源已更新"消息

navigator.serviceWorker.onmessage = function (evt) {
  var message = JSON.parse(evt.data);
  var isRefresh = message.type === 'refresh';
  var isAsset = message.url.includes('asset');
  var lastETag = localStorage.currentETag;
  // ETag header usually contains the hash of the resource so it is a very effective way of check for fresh content.
  var isNew =  lastETag !== message.eTag;
  if (isRefresh && isAsset && isNew) {
    // Escape the first time (when there is no ETag yet)
    if (lastETag) {
      // Inform the user about the update.
      notice.hidden = false;
    }
    //For teaching purposes, although this information is in the offline cache and it could be retrieved from the service worker, keeping track of the header in the localStorage keeps the implementation simple.
    localStorage.currentETag = message.eTag;
  }
};

相关内容

最新更新