Jollyguy
Jollyguy

Reputation: 345

Offline page is not showing in fetch function when using service worker?

I am just started learning about Service Workers just a day ago. Based on my learning, I wanted to create an offline application. I have created 2 pages namely demo.html and offline.html. My aim is when there is no internet connection, I must show offline.html.

I have released my files in my test server. It has SSL connection. When I access my site by typing https://example.com/sampleapp/ where demo.html page is the default. I have installed the service worker and the cache files are downloaded to my machine. Here is where the problem occurs, after disabling my network, I am refreshing the page, here it doesn’t go to offline page, instead it’s showing demo page. When I debug the service-worker.js, and refresh the page, in the js file, it’s goes to fetch function and returns response.status as “OK” instead of going to catch block where I have written that it should go to offline page.

Now instead of refreshing, I mention the demo page in the URL as https://example.com/sampleapp/demo.html, it’s then going to offline page. After I connect to network, if I refresh the page with the same above URL, it’s showing offline page instead of going to demo page. I am not able to tell why this is happening. Can you tell me if the code that I have written is correct?

Please find my service-worker.js code



    // [Working example](/serviceworker-cookbook/offline-fallback/).
    var CACHE_NAME = 'dependencies-cache';
    var REQUIRED_FILES = [
      'offline.html',
      'todo.js',
      'index.js',
      'app1.js'
    ];
    self.addEventListener('install', function(event) {
      // Put `offline.html` page into cache
        event.waitUntil(
        caches.open(CACHE_NAME)
          .then(function (cache) {
              // Add all offline dependencies to the cache
              console.log('[install] Caches opened, adding all core components' +
                'to cache');
              return cache.addAll(REQUIRED_FILES);
          })
          .then(function () {
              console.log('[install] All required resources have been cached, ' +
                'we\'re good!');
              return self.skipWaiting();
          })
      );


      //  var offlineRequest = new Request('offline.html');
      //event.waitUntil(
      //  fetch(offlineRequest).then(function(response) {
      //    return caches.open('offline').then(function(cache) {
      //      console.log('[oninstall] Cached offline page', response.url);
      //      return cache.put(offlineRequest, response);
      //    });
      //  })
      //);
    });

    self.addEventListener('activate', function (event) {
        console.log("Ready for the demo");
    });

    self.addEventListener('fetch', function(event) {
      // Only fall back for HTML documents.
      var request = event.request;
      // && request.headers.get('accept').includes('text/html')
      if (request.method === 'GET') {
        // `fetch()` will use the cache when possible, to this examples
        // depends on cache-busting URL parameter to avoid the cache.
        event.respondWith(
          fetch(request).then(function(response){
              if (!response.ok) {
                  // An HTTP error response code (40x, 50x) won't cause the fetch() promise to reject.
                  // We need to explicitly throw an exception to trigger the catch() clause.
                  throw Error('response status ' + response.status);
              }
              return response;
          }).catch(function (error) {
            // `fetch()` throws an exception when the server is unreachable but not
            // for valid HTTP responses, even `4xx` or `5xx` range.
            //console.error(
            //  '[onfetch] Failed. Serving cached offline fallback ' +
            //  error
              //);
              return caches.open(CACHE_NAME).then(function (cache) {
                  return cache.match('offline.html');
              });
            //return caches.match('offline.html');
            //return caches.open('offline').then(function(cache) {
            //  return cache.match('offline.html');
            //});
          })
        );
      }
      // Any other handlers come here. Without calls to `event.respondWith()` the
      // request will be handled without the ServiceWorker.
    });

Also find my index.js code

if (navigator.serviceWorker.controller) {
  // A ServiceWorker controls the site on load and therefor can handle offline
  // fallbacks.
  debug(
    navigator.serviceWorker.controller.scriptURL +
    ' (onload)', 'controller'
  );
  debug(
    'An active service worker controller was found, ' +
    'no need to register'
  );
} else {
  // Register the ServiceWorker
  navigator.serviceWorker.register('service-worker.js', {
    scope: './'
  }).then(function(reg) {
    //debug(reg.scope, 'register');
    //debug('Service worker change, registered the service worker');
  });
}


// Debug helper
function debug(message, element, append) {
}

From what I have understood about Service Workers, in the fetch function if there is no internet connectivity, I can show offline page. Is this the right way of showing offline page, or should I show the demo page and then in that page if there is no internet connection, then save the data to Index DB? Also I have a question, when there is internet connectivity, I want to check if there is any data in IndexDB and if there is then upload the data to server. In which event should I handle Activate or Fetch?

Thanks,
Jollyguy

Upvotes: 2

Views: 2890

Answers (1)

Richard Williams
Richard Williams

Reputation: 2262

I had a similar problem and it was because in an earlier version of my service worker I had cached my index.html. After removing this from the service worker it remained cached and continued to load even when offline. In your case I suspect '/' is cached, but '/demo.html' is not which explains the behaviour you are seeing.

The resolution in chrome dev tools is either:

  1. Application > Service Workers > Check 'Update on reload' then refresh the page or
  2. Application > Clear storage > Keep all selected and click 'Clear selected'

Upvotes: 1

Related Questions