DEV Community

Lucas Pereira de Souza
Lucas Pereira de Souza

Posted on

Manifest and Service Workers in PWAs

logotech

Here's the English translation of the provided text:

Making Your Web App Amazing: Manifest, Service Workers, and Cache in Practice

If you want your web app to stand out, providing a smooth and reliable user experience, even in unfavorable network conditions, you need to master three fundamental pillars: Web App Manifest, Service Workers, and Cache. Let's dive into each of them, with practical examples for you to implement right away!

1. Web App Manifest: Giving Your App an Identity

The Web App Manifest is a JSON file that provides information about your web app, such as name, icons, theme colors, and startup settings. It's essential for transforming your website into something that looks and behaves like a native application.

  • Creating the Manifest:

    Create a file called manifest.json in the root of your project (or in a specific folder, if you prefer). Add the following properties (and customize them!):

    {
      \"name\": \"My Web App\",
      \"short_name\": \"My App\",
      \"description\": \"An amazing web app for...\",
      \"start_url\": \"/\",
      \"display\": \"standalone\",
      \"background_color\": \"#ffffff\",
      \"theme_color\": \"#3367D6\",
      \"icons\": [
        {
          \"src\": \"images/icon-192x192.png\",
          \"sizes\": \"192x192\",
          \"type\": \"image/png\"
        },
        {
          \"src\": \"images/icon-512x512.png\",
          \"sizes\": \"512x512\",
          \"type\": \"image/png\"
        }
      ]
    }
    
    • name: Full name of your app.
    • short_name: Abbreviated name (used on smaller screens).
    • description: A brief description.
    • start_url: App startup URL.
    • display: Defines how the app is displayed (standalone, fullscreen, minimal-ui, etc.). standalone is the most common, opening the app in a separate window, without the browser's address bar.
    • background_color: Background color of the splash screen (before the app loads).
    • theme_color: Color of the app's status bar.
    • icons: Array of icons for different sizes and devices.
  • Linking in HTML:

    In your HTML file, add the following <link> tag in the <head> to link the manifest:

    <link rel=\"manifest\" href=\"/manifest.json">
    

    Make sure the path to the manifest.json file is correct.

2. Service Workers: The Power of Offline

Service Workers are JavaScript scripts that your browser runs in the background, regardless of whether your site is open. They allow amazing features, such as cache, push notifications, and background synchronization.

  • Registering the Service Worker:

    Create a JavaScript file, for example, sw.js (or another name you prefer), in the root of your project. This will be your service worker.

    In your main JavaScript file (the one containing your main website code), register the service worker:

    if ('serviceWorker' in navigator) {
      window.addEventListener('load', () => {
        navigator.serviceWorker.register('/sw.js')
          .then(registration => {
            console.log('Service Worker registered successfully:', registration);
          })
          .catch(error => {
            console.log('Failed to register Service Worker:', error);
          });
      });
    }
    
    • navigator.serviceWorker.register('/sw.js'): Registers the service worker. The browser will download and execute the sw.js file.
  • Cache in Practice:

    Inside your sw.js file, you can configure the cache. The lifecycle of a Service Worker is based on events. The install event occurs when the service worker is installed for the first time. The fetch event occurs every time the browser makes a request for a resource (HTML, CSS, JavaScript, images, etc.).

    const CACHE_NAME = 'my-web-app-cache-v1'; // Use versioning to update the cache
    const urlsToCache = [
      '/',
      '/index.html',
      '/styles.css',
      '/script.js',
      '/images/icon-192x192.png',
      '/images/icon-512x512.png'
    ];
    
    self.addEventListener('install', event => {
      event.waitUntil(
        caches.open(CACHE_NAME)
          .then(cache => {
            console.log('Cache opened');
            return cache.addAll(urlsToCache);
          })
      );
    });
    
    self.addEventListener('fetch', event => {
      event.respondWith(
        caches.match(event.request)
          .then(response => {
            // If found in the cache, return the response from the cache
            if (response) {
              console.log('Retrieved from cache:', event.request.url);
              return response;
            }
            // If not in the cache, make the request to the network
            return fetch(event.request)
              .then(response => {
                // Clone the response so we can use it in the cache and return it
                const responseToCache = response.clone();
                caches.open(CACHE_NAME)
                  .then(cache => {
                    cache.put(event.request, responseToCache);
                  });
                return response;
              });
          })
      );
    });
    
    self.addEventListener('activate', event => {
      // Clean up old caches (previous versions)
      event.waitUntil(
        caches.keys().then(cacheNames => {
          return Promise.all(
            cacheNames.map(cacheName => {
              if (cacheName !== CACHE_NAME) {
                console.log('Cleaning up old cache:', cacheName);
                return caches.delete(cacheName);
              }
            })
          );
        })
      );
    });
    
    • CACHE_NAME: Cache name. It is crucial that you version it. When you make changes to the files that will be cached, increase the version (e.g., my-web-app-cache-v2). The service worker will install a new version of the cache and, in the activate event, will remove the old caches.
    • urlsToCache: Array of URLs you want to store in the cache.
    • self.addEventListener('install'): Occurs when the service worker is installed. We use caches.open() to open or create the cache and cache.addAll() to add the resources to the cache.
    • self.addEventListener('fetch'): Occurs when the browser makes a request. First, we try to find the request in the cache (caches.match()). If found, we return the response from the cache. Otherwise, we make the request to the network (fetch()). Then, we clone the response (because it can only be read once) and add it to the cache for future use.
    • self.addEventListener('activate'): Occurs when the service worker is activated. This is where you can clean up old caches, ensuring that only the latest version of your cache is used.

3. Updating the Service Worker

When you make changes to your service worker or the files it stores in the cache, the update happens in a few steps:

  1. Code Change: Make changes to your sw.js file and/or your static files (HTML, CSS, JavaScript, images).
  2. Update in the Browser: The browser will detect the changes and try to reinstall the service worker. It will check if there is a new version of the sw.js file.
  3. Installation of the New Version: The new service worker is installed, but the old one continues to handle requests until all tabs of your site are closed or reloaded.
  4. Activation: When the new service worker is ready and the old one is no longer in use, the activate event is triggered in the new service worker. It is at this moment that you can clean up the old caches.

Extra Tips:

  • Test in Incognito/Private Mode: Use incognito mode to test the behavior of your service worker, as it can be easier to debug than caching data in other browsers.
  • Debug Tools: Use your browser's developer tools (usually accessible with F12) to inspect the status of the service worker, see the requests, analyze the cache, and debug errors.
  • Consider Workbox: Workbox is a Google library that simplifies the creation and management of service workers. It offers features like predefined caching strategies, update management, and more.

By implementing the Web App Manifest, Service Workers, and Cache, you'll be on the right track to create web apps that offer a high-quality user experience, even in adverse conditions. Start implementing these techniques today and see the difference they make in your project!

Top comments (0)