使用Node.js服务器时,Service Worker在离线模式下无法正常工作

10
  • 我正在尝试构建一个具有“离线优先策略”的PWA
    • 源文件的服务器是一个NodeJS服务器
    • 我目前在本地主机上测试这个服务器(不确定是否会产生影响?)。
    • 服务工作者+缓存似乎很好,但在离线模式下我只能获得Chrome离线页面

让我们深入了解:

通过http://localhost:8080/place/test URL提供服务的页面具有一些客户端JS,在其中我注册了一个服务工作者:

client.js

    if ('serviceWorker' in navigator) {
        navigator.serviceWorker
                 .register(rootPath+'/js/service-worker.js')
                 .then(function() { console.log('Service Worker Registered'); });
    }

service-worker.js(基于Google PWA教程)

var cacheName = 'myCacheVersion';
var filesToCache = [
    '../',
    '../place/test',
    '../js/client.js',
    '../js/service-worker.js',
    "../css/style.css"
];


self.addEventListener('install', function(e) {
  console.log('[ServiceWorker] Install');
  e.waitUntil(
    caches.open(cacheName).then(function(cache) {
      console.log('[ServiceWorker] Caching app shell');
      return cache.addAll(filesToCache);
    })
  );
});

self.addEventListener('activate', function(e) {
  console.log('[ServiceWorker] Activate');
  e.waitUntil(
    caches.keys().then(function(keyList) {
      return Promise.all(keyList.map(function(key) {
        if (key !== cacheName) {
          console.log('[ServiceWorker] Removing old cache', key);
          return caches.delete(key);
        }
      }));
    })
  );
  return self.clients.claim();
});

self.addEventListener('fetch', function(e) {
  console.log('[ServiceWorker] Fetch', e.request.url);
  e.respondWith(
    caches.match(e.request).then(function(response) {
      return response || fetch(e.request);
    })
  );
});

在Dev Tools控制台中,一切似乎都很好:
  • SW已注册
  • 缓存包含我想要缓存的元素
但是当我勾选“离线模式复选框”并刷新我的页面网址:http://localhost:8080/place/test,我只得到了“Google Chrome离线Web页面”。
=》我错过了什么?(与nodeJs有关吗?与本地主机环境有关吗?与我的实现有关吗?)
我已经为这个问题苦苦挣扎了一段时间...
我在“应用程序”选项卡中进行了检查,我的服务工作者显示为已激活并正在运行。
注意:如果在此处找到了类似的问题,但没有满意的答案:使用nodejs服务器时离线模式下无法运行服务工作者

你说软件已注册;(就像你在链接的另一个问题的评论中提到的那样)它是否显示在“应用程序”选项卡中? - Ed.
1
是的,它显示为“已激活并正在运行”。 - B. B.
1个回答

12

本质上,这与此处回答的问题相同:Service worker is caching files but fetch event is never fired

如果您查看控制台,您会发现尽管发生了安装、激活、缓存和注册,但“fetch”事件不会发生。这是因为您将服务工作者定位在js下,所以出于安全原因,Chrome(等)不会将其用于除了同一目录或以下目录中的任何URL之外的URL。

如果您将client.jsservice-worker.js放在同一级别而不是在js子目录中,它们就会全部开始运作。这将需要更新文件的内容,我将在下面提供参考。

一个小细节:我愚蠢地在Windows箱上使用了IIS来处理此问题,而且由于这个原因和Chrome,它们紧紧地保留了具有过时JS文件位置的缓存HTML文件。我不得不将它们复制到一个子目录中,创建新的URL来测试解决方案。

index.html

<head>
<script src="client.js"></script>
</head>
<body>
<a href="cachetest.html">link to ct</a>
</body>

cachetest.html:

<head>
<script src="client.js"></script>
</head>
<body>cachetest</body>

client.js:

if ('serviceWorker' in navigator) {
    navigator.serviceWorker
             .register('service-worker.js')
             .then(function() { console.log('Service Worker Registered'); });
}

serviceworker.js:

var cacheName = 'myCacheVersion';
var filesToCache = [
    '',
    'cachetest.html',
    'client.js',
    'service-worker.js',
//    "css/style.css"
];


self.addEventListener('install', function(e) {
  console.log('[ServiceWorker] Install');
  e.waitUntil(
    caches.open(cacheName).then(function(cache) {
      console.log('[ServiceWorker] Caching app shell');
      return cache.addAll(filesToCache);
    })
  );
});

self.addEventListener('activate', function(e) {
  console.log('[ServiceWorker] Activate');
  e.waitUntil(
    caches.keys().then(function(keyList) {
      return Promise.all(keyList.map(function(key) {
        if (key !== cacheName) {
          console.log('[ServiceWorker] Removing old cache', key);
          return caches.delete(key);
        }
      }));
    })
  );
  return self.clients.claim();
});

self.addEventListener('fetch', function(e) {
  console.log('[ServiceWorker] Fetch', e.request.url);
  e.respondWith(
    caches.match(e.request).then(function(response) {
      return response || fetch(e.request);
    })
  );
});

4
你做得很好!我只需要将我的service-worker.js移动到我的根目录,并对文件路径和缓存文件列表路径进行一些更改,就可以使它工作了... 以后要注意:记住service-worker仅能访问其级别及以下的内容...非常感谢!(我已经为你的答案点赞了,但由于我是新手,在屏幕上还没有显示出来...) - B. B.
谢谢!祝你其他事情顺利。我要看看这是否也是另一个问题的答案。 - Ed.
或者,你可以! :-) - Ed.
1
我还将我的Service Worker添加到了应用程序的根目录下<domain.com>/service-worker.js,然后事情开始工作了。谢谢! - Clifford Fajardo
1
谢谢,安装注册SW和实际的Service Worker修复了问题。 - Gesha

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接