使用Node.js服务器时,Service Worker无法在离线模式下运行。

4

我正在创建一个新的 PWA 项目。

当我开发时,没有使用 Node.js(用于运行 socket.io),只是像预期和需要的那样离线运行。

但是当与 Node.js 服务器集成时,应用程序在线运行良好,没有任何问题。但是当我切换到离线模式时,我的服务无法运行,但显示为离线浏览器。

这是我的 Node.js 服务器代码:

var express = require('express');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var cors = require('cors');

app.use(cors());
app.use(express.static(__dirname + '/'));

app.use(function(req, res, next){
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  next();
});


io.on('connection', function(socket) {
  console.log('new connection');

  socket.on('afterBid', function(data) {
    io.emit('bcCurrentBid', {
      current_bidding: data.auction_current_bidding,
      user_id_dominated: data.user_id_dominated
    });
  });

});

server.listen(9991, function() {
  console.log('server up and running at 2205 port');
});

以下是我的服务在index.js中的注册内容:

if ('serviceWorker' in navigator && 'PushManager' in window) {
  console.log('Service Worker and Push is supported');

   window.addEventListener('load', function() {
   navigator.serviceWorker
             .register('./service-worker.js')
             .then(function() { console.log('Service Worker Registered'); });
   });
 }

这是我的 service-worker.js 文件:

var cacheName = 'Auction-v2';
var filesToCache = [
  'index.html',
  'server.js',
  '/',
  './app/app.js',
  './app/listAuctionController.js',
  './app/auctionDetailController.js',
  './app/service/auctionDataService.js',
  './media/frontend/images/auction_logo_white.png',
  // './media/frontend/',
  // './media/catalog/',
  // './view/',
  './lib/css/materialize.min.css',
  './lib/css/owl.carousel.min.css',
  './lib/css/jquery.countdown.css',
  './lib/css/owl.theme.default.min.css',
  './lib/css/materialize-icon.css',
  './lib/js/jquery.min.js',
  './lib/js/jquery.lazyLoad.js',
  './lib/js/jquery.maskMoney.js',
  './lib/js/jquery.countdown.min.js',
  './lib/js/materialize.min.js',
  './lib/js/owl.carousel.min.js',
  './lib/js/angular/angular.min.js',
  './lib/js/angular/angular-route.min.js',
  './lib/js/angular/angular-sanitize.min.js',
  './lib/js/angular/angular-locale_id-id.js',
  './lib/js/angular/angular-animate.min.js',
];

var dataCacheName = 'Auction-Data-v1';

// SW Install
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('fetch', function(e) {
  // console.log('[Service Worker] Fetch', e.request.url);
  var dataUrl = '/backendFrame/public/api/v1/';
  var dataUrl2 = '/view/';
  if (e.request.url.indexOf(dataUrl) > -1 || e.request.url.indexOf(dataUrl2)) {
    /*
     * When the request URL contains dataUrl, the app is asking for fresh
     * weather data. In this case, the service worker always goes to the
     * network and then caches the response. This is called the "Cache then
     * network" strategy:
     * https://jakearchibald.com/2014/offline-cookbook/#cache-then-network
     */
    e.respondWith(
      caches.open(dataCacheName).then(function(cache) {
        return fetch(e.request).then(function(response){
          // console.log('url to cache =' + e.request.url);
          cache.put(e.request.url, response.clone());
          return response;
        });
      })
    );
  } else {
    /*
     * The app is asking for app shell files. In this scenario the app uses the
     * "Cache, falling back to the network" offline strategy:
     * https://jakearchibald.com/2014/offline-cookbook/#cache-falling-back-to-network
     */
    e.respondWith(
      caches.match(e.request).then(function(response) {
        return response || fetch(e.request);
      })
    );
  }
});

// SW Activate
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  && key !== dataCacheName) {
          console.log('[ServiceWorker] Removing old cache', key);
          return caches.delete(key);
        }
      }));
    })
  );
  return self.clients.claim();
});

谢谢,也许有人能给我解决方案。


没有看到你的 service-worker.js 的内容,很难给出太多反馈。一个普遍的建议是,Service Worker 无法拦截 WebSocket API 请求/响应,也就是说它无法处理你的 socket.io 流量。 - Jeff Posnick
@JeffPosnick,但是Service Worker和Node.js服务器可以一起运行吗?我只需要运行我的Node.js服务器,并且在离线模式下,Service Worker能够从缓存中显示应用程序。 - Medianto Jaelani
2个回答

2
我在这里发布了一个类似的问题并得到了答案: Service Worker不适用于使用Node.js服务器的离线模式 简短地说,记住服务工作器的范围是其自己的目录和其下的文件夹……它不能访问你的lib或app目录 更详细地说,这意味着如果你的内容从 https://example.com/ 开始,则您的服务工作器必须驻留在 https://example.com/service-worker.js 。如果将其放置在 https://example.com/js/service-worker.js ,则无法正常工作。

1
服务工作者只是从您的Web服务器提供的JavaScript文件。无论是不是Node.js都没关系。
您是否检查了Chrome调试工具中的“应用程序”选项卡,以查看服务工作者是否已加载?如果是,请共享“service-worker.js”文件的代码。您还可以在注册服务工作者时添加一个“catch”部分。如果服务工作者无法加载,这可能会显示出问题所在。

window.addEventListener('load', function() {
  navigator.serviceWorker
    .register('./service-worker.js')
    .then(function() { console.log('Service Worker Registered'); })
    
    .catch(function (err) {
            console.log('ServiceWorker registration failed: ', err);
    });
    
});


我编辑了我的问题并添加了我的service-worker.js文件。我遇到的问题是,当我不使用nodejs运行时,我的应用程序可以在离线模式下使用service worker运行。@Sorskoot - Medianto Jaelani

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