Lesson 18-HTML5 Service Works Offline Application

HTML5 Service Workers is a script that runs in the background of the browser. It is independent of the main thread of the web page, allowing developers to intercept and control network requests, and provide offline caching, push notifications and other functions, thereby significantly improving the user experience and reliability of web applications. sex.

Service Workers Basics

Registration and life cycle:

  • Registration: Use the navigator.serviceWorker.register() method to register the Service Worker script in the web page. Usually registered in the <script> tag of the main page or after asynchronous loading.
  • Life cycle: Service Worker goes through states such as install, activate, idle, event received, and terminate. Developers handle tasks at each stage through event listeners (such as install, activate, fetch, etc.) in Service Worker scripts.

Create Service Worker script

  • Service Worker script location: usually placed in the root directory or subdirectory of the website, such as /sw.js. Make sure the script is accessible via HTTPS protocol as Service Workers only work in a secure context.
  • Cache strategy: Define the cache strategy in the Service Worker script to decide which resources should be cached and when the cache should be updated.
//sw.js

//Define cache name
const CACHE_NAME = 'my-offline-app-v1';

// List of resources to cache
const urlsToCache = [
 '/',
 '/index.html',
 '/styles.css',
 '/app.js',
 '/images/icon.png',
 // Other resources...
];

//Installation phase
self.addEventListener('install', (event) => {
    event.waitUntil(
    caches.open(CACHE_NAME).then((cache) => {
        return cache.addAll(urlsToCache);
    })
    );
});

//activation phase
self.addEventListener('activate', (event) => {
  event.waitUntil(
    caches.keys().then((cacheNames) => {
      return Promise.all(
        cacheNames.map((cacheName) => {
          if (cacheName !== CACHE_NAME) {
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
});

Cache and network request processing

  • fetch event: Service Worker listens to the fetch event. When the browser initiates a network request, it can intercept and return the resources in the cache, or provide backup resources when the network request fails.
self.addEventListener('fetch', (event) => {
    event.respondWith(
        caches.match(event.request).then((cachedResponse) => {
        // If the requested resource is in the cache, return directly
        if (cachedResponse) {
            return cachedResponse;
        }

        // Otherwise, try to get it from the network
        return fetch(event.request).then((networkResponse) => {
            // Store a copy of the network response in the cache (optional, depending on the strategy)
            caches.open(CACHE_NAME).then((cache) => {
            cache.put(event.request, networkResponse.clone());
        });

        return networkResponse;
        }).catch(() => {
            // Network request failed, return offline page (or custom error page)
            return caches.match('/offline.html');
            });
        })
    );
});

Update cache

  • Update strategy: When the Service Worker script changes, the browser will automatically try to update. In the install event, you can create a new cache with a new cache name, and clean up the old cache in the activate event.
  • Actively trigger updates: You can periodically check for updates to the Service Worker script on the web page (such as using navigator.serviceWorker.controller?.registration.update()), or listen to the message event in the Service Worker, and the web page sends an update instruction to actively trigger the update.

Other features

Push notifications: Through the push and notificationclick events of Service Worker, you can implement the Web Push notification function, so that users can receive notifications even if they are not in the app.

Background synchronization: Using the sync event, you can perform delayed background tasks when the network is restored, such as synchronizing data saved offline to the server.

Testing and debugging

Developer tools: Use the browser’s developer tools (such as the “Application” panel of Chrome DevTools) to view registered Service Workers, cached content, push subscription status, etc., and simulate offline state for testing.

Log output: Use console.log() to log in the Service Worker script to help debugging.

Example

sw.js (Service Worker script)

// Define the cache name
const CACHE_NAME = 'my-offline-app-v1';

// List of resources to cache
const urlsToCache = [
    '/',
    '/index.html',
    '/styles.css',
    '/app.js',
    '/images/icon.png',
    // Other resources...
];

// Installation phase
self.addEventListener('install', (event) => {
  console.log('[Service Worker] Installing...');
  event.waitUntil(
    caches.open(CACHE_NAME).then((cache) => {
      console.log('[Service Worker] Caching app shell');
      return cache.addAll(urlsToCache);
    })
  );
});

// Activation Phase
self.addEventListener('activate', (event) => {
  console.log('[Service Worker] Activating...');
  event.waitUntil(
    caches.keys().then((cacheNames) => {
      return Promise.all(
        cacheNames.map((cacheName) => {
          if (cacheName !== CACHE_NAME) {
            console.log(`[Service Worker] Removing old cache ${cacheName}`);
            return caches.delete(cacheName);
          }
        })
      );
    })
  );

  console.log('[Service Worker] Activated');
});

// Caching and network request processing
self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request).then((cachedResponse) => {
      if (cachedResponse) {
        console.log(`[Service Worker] Serving from cache: ${event.request.url}`);
        return cachedResponse;
      }

      console.log(`[Service Worker] Fetching: ${event.request.url}`);
      return fetch(event.request).then((networkResponse) => {
        // Optional: Cache network responses
        // caches.open(CACHE_NAME).then((cache) => {
        //   cache.put(event.request, networkResponse.clone());
        // });

        return networkResponse;
      }, () => {
        // The network request fails and returns an offline page (or a custom error page)
        return caches.match('/offline.html');
      });
    })
  );
});

index.html (main page)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Service Worker Demo</title>
  <link rel="stylesheet" href="/styles.css">
  <script>
    if ('serviceWorker' in navigator) {
      window.addEventListener('load', function() {
        navigator.serviceWorker.register('/sw.js')
          .then((registration) => {
            console.log('[App] Service Worker registered:', registration);
          })
          .catch((error) => {
            console.error('[App] Service Worker registration failed:', error);
          });
      });
    } else {
      console.log('[App] Service Worker is not supported');
    }
  </script>
</head>
<body>
  <h1>Welcome to the Service Worker Demo</h1>
  <p>This page and its resources are cached for offline use.</p>
  <img src="/images/icon.png" alt="Icon">
  <script src="/app.js"></script>
</body>
</html>
  1. In sw.js, define the cache name (CACHE_NAME) and the list of resources to be cached (urlsToCache). In the install event handler, open the cache and add the specified resources. In the activate event handler, delete the old cache.
  2. In the fetch event handler, return the resources in the cache first, otherwise try the network request. When the network request fails, return the offline page (here it is assumed that /offline.html exists).
  3. In index.html, check whether the browser supports Service Worker. If it does, register sw.js after the page is loaded. You can see the registration status and log output of Service Worker in the console.
Share your love