服务工作者不在离线模式下使用节点js服务器

时间:2017-08-27 17:43:01

标签: javascript node.js localhost service-worker progressive-web-apps

  • 我正在尝试使用脱机第一个策略构建 PWA
    • 源文件的服务器是 NodeJS服务器
    • 我目前正在 localhost 节点服务器上测试它(不确定它有影响吗?)。
    • 服务工作者+缓存似乎很好,但在离线模式下我只能获得Chrome离线版

让我们详细了解一下:

提供的页面(通过http://localhost:8080/place/test url)有一些客户端JS,我在其中注册了Service Worker:

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);
    })
  );
});

在开发工具控制台中,一切似乎都很好:

  • SW已注册
  • 缓存包含我想要缓存的元素

但是当我选中离线模式复选框并刷新我的网页网址:http://localhost:8080/place/test时,我只能获得 Google Chrome离线网页

=>我在那里错过了什么?(是否与nodeJs有关?使用localhost环境?我的实现?)

我现在一直在努力解决这个问题......

我已检查“应用程序”选项卡,我的服务工作人员显示为已激活且正在运行。

注意:如果在此处找到类似的问题,但在那里没有令人满意的答案:Service worker not run in offline mode using nodejs server

1 个答案:

答案 0 :(得分:8)

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

如果您查看控制台,您会看到在安装,激活,缓存和注册都发生时,“获取”不会。这是因为您将服务工作者定位在js下,因此出于安全原因,Chrome(等)不会将其用于除同一目录或以下目录之外的任何网址。

如果您将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);
    })
  );
});