首页 > 解决方案 > 安装新的 serviceworker 时页面没有响应。每次小更新都会重新获取所有静态文件

问题描述

  1. 在安装新的 serviceworker 时,我们的页面变得无响应。我们的目标是安装新的 serviceworker,但要防止安装处理程序请求与主页请求争夺带宽的资源。
  2. serviceworker 安装事件需要大量时间,因为所有文件都被再次获取,即使是在很小的更新之后。serviceworker 应该只在更新后(重新)获取动态文件(参见下面代码中的 mutableRequests)。在 serviceworker 更新后应该只获取新的静态文件,而不是所有的静态文件(参见下面代码中的 immutableRequests)。

请在代码中找到以下注释,这些注释解释了我已经尝试过的事情。

// Register the serviceworker:

  if ('serviceWorker' in navigator) {
   window.addEventListener('load', function() {
     navigator.serviceWorker
            .register('/sw.js')
            .then(function() { console.log("Service Worker Registered"); });
   });
  }
// The serviceworker:

'use strict';

// To update the version of the serviceworker:
var CACHE_NAME = 'swwo-cache-v143';

// The 'static' assets:
var immutableRequests = [

    // Many assets here:
    '/js/awesomplete.js',
    '/js/bootstrap.min.js',
    '/img/earth-from-space.jpg'
    // ETC...

];

// The 'dynamic' assets:
var mutableRequests = [

        // Only a few assets here:          
        '/index.html',
        '/legal.html'
        // ETC...       

];

// Here the goal was to make sure that all the mutableRequests are being fetched again, and only the NEW immutableRequests:
self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open(CACHE_NAME).then(function(cache) {
      var newImmutableRequests = [];
      return Promise.all(
        immutableRequests.map(function(url) {
          return caches.match(url).then(function(response) {
            if (response) {
              return cache.put(url, response);
            } else {
              newImmutableRequests.push(url);
              return Promise.resolve();
            }
          });
        })
      ).then(function() {
        return cache.addAll(newImmutableRequests.concat(mutableRequests));
      });
    })
  );
});


self.addEventListener('fetch', event => {
  var requestURL = new URL(event.request.url);

// Try the cache first:
  if (requestURL.origin == location.origin && requestURL.pathname == '/') {
    event.respondWith(caches.match('/index.html'));
    return;
  }

// Analytics exception:
  else if (requestURL.host === 'www.google-analytics.com') {
  event.respondWith(fetch(event.request));
}

 else {

 event.respondWith(
// Try the cache:
    caches.match(event.request)
// Fall back to the network:
      .then(response => response || fetch(event.request))
// A general fallback:
      .catch(function() {   
       return caches.match('/offline/index.html');

      })
  );}

});


// Removing the old cache:
self.addEventListener('activate', function(event) {
  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames.map(function(cacheName) {
          if (CACHE_NAME !== cacheName) {
    console.log('Deleting out of date cache:', cacheName);
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
});

标签: javascriptservice-worker

解决方案


1.

          return caches.match(url).then(function(response) {

有一个错误:您应该调用 cache.match 来匹配您感兴趣的缓存。不是带有“s”的 cacheS :)

2.

如果您总是更新缓存的名称

// To update the version of the serviceworker:
var CACHE_NAME = 'swwo-cache-v143';

那么从那里将找不到以前获取和缓存的资产,对吗?

请记住:即使 SW 脚本文件中的 SINGLE BYTE 更改,浏览器也会认为 SW 脚本是新的,因此您要缓存的资产中的任何更改都会使 SW 对浏览器来说是新的。如果您不需要任何东西,则无需在任何地方保留单独的版本号。这里似乎引起了问题。如果你想拥有它,你可以将版本号放在评论中。

还有一件事要注意:如果您真的不需要软件尽快注册/更新,您可以推迟它。使用 setTimeout 将 SW 注册延迟 15 秒或其他任何时间,以便用户尽快使用该页面。这使应用程序更流畅。


推荐阅读