© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2022
V. K. KotaruBuilding Offline Applications with Angularhttps://doi.org/10.1007/978-1-4842-7930-4_4

4. Service Workers

Venkata Keerti Kotaru1  
(1)
-, Hyderabad, Telangana, India
 

Service workers run in the background on your browser. They provide a foundation for modern web applications and are installable, work offline, and are reliable in low-bandwidth situations. This chapter provides an introduction to service workers. It discusses the caching capabilities of service workers and how to use them in an Angular application. It details the lifecycle of a service worker. Next, the chapter discusses Angular’s configurations and features while working with the service workers. It explains how to implement a cache for the Web Arcade sample application. Toward the end, it provides details about browser compatibility.

Service workers are a network proxy running on the browser. They can intercept outgoing network requests from the browser. These requests include an application’s JavaScript bundle files, stylesheets, images, font, data, etc. You may program a service worker to respond to a request from the cache. This enables web applications to be resilient to network speeds and a loss of connectivity. Unlike a traditional web application, which returns a “page not found” error when you lose connectivity, service workers enable the application to utilize installed and cached resources. You can program the application to load cached data or show a graceful error message. Even in low-bandwidth scenarios, service workers enable you to build fluid and responsive applications with great user experiences.

The service workers are preserved even after the application or the browser is closed. To see a list of active service workers, navigate to the page chrome://inspect/#service-workers on Google Chrome or edge://inspect/#service-workers on Microsoft Edge. See Figure 4-1. Notice the popular websites including Angular’s Angular.io among the applications that use the service workers. Also notice that the Web Arcade sample application’s dev URL localhost:8080 has registered a service worker.
Figure 4-1

Inspecting the service workers on Google Chrome

Note

To see all the service workers registered by various web applications you have accessed on your computer, launch the service worker internals page. Notice that the first URL, chrome://inspect/#service-workers, listed only the active service workers. Access the service worker internals by navigating to chrome://serviceworker-internals on Google Chrome (or edge://serviceworker-internals on Microsoft Edge).

Please note this page might be deprecated in the future. The chrome://inspect/#service-workers URL might include all the service worker debug features.

Service Worker Lifecycle

This section details the service worker lifecycle and its states running in the background (on the browser). See Figure 4-2, which depicts a service worker lifecycle. It begins by registering a new service worker. A web application using a service worker registers on loading in the browser. The “register” can occur every time a user loads the application. The browser ignores a fresh registration if the service worker has already been registered.

Successful registration of a service worker triggers an install event. A typical install event handles the caching logic. All the static resources including application bundles, images, fonts, and stylesheets are cached during the install event. These are configurable.

The service worker installation is atomic. A failure in downloading and caching one or more resources causes the event to error out completely. The next time the user accesses the website, it attempts to install it again. This is to ensure there are no partially installed applications causing unforeseen problems and bugs.

While the application is open, an installed service worker is activated. It runs in the background and acts as a proxy to all the network calls. Depending on the application logic and configuration, you may serve the data from the cache. If the data is not found in the cache, invoke the network service and retrieve data over the network.

If the application or the service worker is not in use, the service worker terminates to save memory. When needed, it activates the service worker. Notice the terminate button in Figure 4-1 (in the browser window) for manually terminating an active service worker. You may use this to force close the service worker. It helps relaunch the service worker afresh. If your computer is running low on resources, you may terminate a service worker to save memory. Also, notice the Inspect link, which launches the dev tools allowing you to explore network resources and the application source code.

See Figure 4-2 for a depiction of the workflow and events.
Figure 4-2

Service worker lifecycle

Service Worker in an Angular Application

Angular makes it easier to use the service worker and caching features in your application. Angular scaffolds a lot of the functionality described in the previous section “Service Worker Lifecycle,” especially the caching features. This section details out-of-the-box Angular features for integrating the service workers.

Angular CLI generates ngsw-config.json when you add @angular/pwa to the project. It provides a service worker configuration for an Angular application. The Angular build process uses this configuration. One of the aspects of configuration is a list of static and dynamic resources to be cached and installed. Static resources include JavaScript bundle files that constitute the application, stylesheets, images, font, and icons. Typical dynamic resources include data responses.

A ngsw-config.json file includes the following sections :
  • appData: Remember, the Web Arcade Angular application is installable and maintains versions. This field in the configuration provides a brief description of the application version. As you update the application, use this field to provide meaningful details about the upgrade and the version of the software.

  • index: This specifies the root HTML file for the Angular application and the single-page application (SPA). In the Web Arcade sample application, it is index.html in the src directory. With this field index, you are providing a link to the starting point of the application. As you will see next, Web Arcade caches this file using the service worker.

  • assetGroups: This is a configuration for assets, typically JavaScript application bundles, stylesheets, font, images, icons, etc. The assets could be part of the Angular project or downloaded from a remote location like a content delivery network (CDN).
    • Notice Web Arcade’s ngsw-config file in Listing 4-1. It includes files that constitute the application, i.e, index.html, all the JavaScript bundles, and the CSS files. It also includes assets such as images, icons, fonts, etc.

Note

Remember, in Web Arcade the SASS files compile to CSS. Service workers are working on the build output of the Angular application. All the files including JavaScript bundles, compiled CSS, images, etc., are relative to the dist directory (output of the yarn build command).

  1. 1.
    You can configure multiple assetGroups. Notice that the field is an array. You can list JSON objects with the configuration details. An assetGroup object defines the following fields :
    1. a.

      name: This is an arbitrary title for an asset group.

       
    2. b.
      resources: The resources are the files or URLs to be cached by the service worker. As mentioned, the files could be JavaScript files, CSS stylesheets, images, icons, etc. On the other hand, for resources such as fonts (and a few other libraries), you may use CDN locations, which are URLs.
      1. i.

        files: This is an array of files configured for the service worker to cache.

         
      2. ii.

        urls: This is an array of URLs configured for the service worker to cache.

         

      At build time, it is not likely you will know every file to be cached. Hence, the configuration allows you to use file and URL patterns. See the section “Pattern Match Resources to Cache” for more details.

       
    3. c.
      installMode: Install mode determines how to cache the resources for the first time when there is no existing version of the service worker on the browser. It supports two modes of caching.
      1. iii.

        prefetch: Cache all the resources, files, and URLs at the beginning. The service worker does not wait for the resource to be requested by the application. As and when the application requests, the resource is readily available in the cache.

        This approach is useful for the root index.html file, core application bundles, primary stylesheets, etc. However, the prefetch install mode could be bandwidth intensive.

        Prefetch is the default install mode, when no configuration value is provided.

         
      2. iv.

        lazy: Cache resources only when the application requests it for the first time. If a particular resource is configured but never requested, it is not cached. It is efficient. However, the resource is available offline only from the second use.

         
       
     
  2. 2.
    updateMode: Update mode determines how to cache the resources when a new version of the application is found. This is for a service worker (an Angular application) that is already installed in the browser. As you know, unlike a typical web application, the service worker enables caching an Angular application. It also allows you to discover and install updates as and when available. It supports two modes of caching.
    1. a.

      prefetch: Download and cache all the resources, files, and URLs while updating the application. The service worker does not wait for the resource to be requested by the application. As and when the application requests a resource, it is readily available in the cache.

      Default: When no configuration value is provided, it uses the value set for installMode.

       
    2. b.

      lazy: Cache resources only when the application requests it for the first time. If a particular resource is configured but never requested, it is not cached. This is efficient. However, the resource is available offline only from the second use.

      This configuration value is overridden if installMode is prefetch. For it to cache truly in lazy mode, installMode needs to be lazy as well.

       
     
  3. 3.
    dataGroups: While assetGroups enables caching application assets, largely static resources, dataGroups help cache dynamic data requests. It is an array of data group objects. You can configure multiple dataGroups. You can list JSON objects with the configuration details. A dataGroup object defines the following fields :
    1. a.

      name: This is an arbitrary title for a data group.

       
    2. b.

      urls: This is an array of strings that configure a list of URLs or a list of patterns matching the URLs. Unlike assetGroups, the pattern doesn’t support matching with ? as it is a common character for query strings in a URL.

       
    3. c.

      version: This helps identify the availability of a new version of dataGroup resources. The service worker discards old versions of the cache, fetches new data, and caches the new URL responses. If a version is not provided, it defaults to 1.

      Versioning data groups is useful especially when a resource is incompatible with the old URL responses.

       
    4. d.
      cacheConfig: This defines a configuration for the data cache policy. It includes the following fields:
      1. i.

        maxSize: This defines an upper limit for the size of the data to be cached. It is a good practice to limit the size by design. Browsers (like any other platform) manage and allocate memory for each application. If the application exceeds the upper limit, the entire dataset and the cache could be evicted. Hence, design a system to limit the cache size and prevent unforeseen results caused due to eviction.

         
      2. ii.

        maxAge: dataCache is dynamic in nature. Often data changes at the source. Caching data for too long could cause the application to use obsolete fields and records. A service worker configuration provides a mechanism to automatically clear the data at periodic intervals, ensuring the application does not use stale data. In an example, imagine interest rates are updated once in a day. This means the cached interest rate values need to expire in 24 hours. On the other hand, users’ profile pictures are rarely updated. Hence, they can be stored in the cache longer.

        You may qualify the max age value with one or more of the following:

        d stands for days. For example, use 7d for seven days.

        h stands for hours. For example, use 12h for 12 hours.

        m stands for minutes. For example, use 30m for 30 minutes.

        s stands for seconds. For example, use 10s for ten seconds .

        u stands for milliseconds, For example, use 500u for half a second.

        You can mix and match to create a composite value. For example, 2d12h30m stands for 2 days, 12 hours, and 30 minutes.

         
      3. iii.

        timeout: Depending on the dataCache strategy (see the next item), often data requests attempt to use responses over the network. Only if the network request is taking too long (or fails), it uses the cached response.

        The timeout defines a value after which the service worker ignores the network request and responds with a cached value.

        You may qualify the timeout value with one or more of the following:

        d stands for days. For example, use 7d for seven days.

        h stands for hours. For example, use 12h for 12 hours.

        m stands for minutes. For example, use 30m for 30 minutes.

        s stands for seconds. For example, use 10s for ten seconds.

        u stands for milliseconds, For example use 500u for half a second.

        You can mix and match to create a composite value. For example 2d12h30m stands for 2 days, 12 hours, and 30 minutes .

         
      4. iv.
        strategy: A service worker can use one of the following two strategies:
        • performance: For few data requests, the Angular application may prioritize performance, instructing the service worker to use cached responses. The response is returned faster as it comes from the local cache. A new network service request is sent only after maxAge (see the previous bullet point on maxAge). In an example, it is useful with the interest rates request that updates nightly. Imagine maxAge is set to 1d, and the service worker uses the cache for 24 hours after which the cache expires.

        • freshness: In many cases, the Angular application configures the service worker to fetch data over the network first, before using the cached data. Imagine on a slow network, if the data request timed out, the service worker uses the cache so that the application is still usable.

         
       
     

Web Arcade’s Service Worker Configuration

Consider Listing 4-1. It is the default configuration file generated for the Web Arcade project.
--- ngsw-config.json ---
01: {
02:   "$schema": "./node_modules/@angular/service-worker/config/schema.json",
03:   "index": "/index.html",
04:   "assetGroups": [
05:     {
06:       "name": "app",
07:       "installMode": "prefetch",
08:       "resources": {
09:         "files": [
10:           "/favicon.ico",
11:           "/index.html",
12:           "/manifest.webmanifest",
13:           "/*.css",
14:           "/*.js"
15:         ]
16:       }
17:     },
18:     {
19:       "name": "assets",
20:       "installMode": "lazy",
21:       "updateMode": "prefetch",
22:       "resources": {
23:         "files": [
24:           "/assets/**",
25:           "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
26:         ]
27:       }
28:     }
29:   ]
30: }
Listing 4-1

ngsw-config.json File

  • Notice the field assetGroups on line 4. Between lines 5 and 17 is the first asset group object. This object details resources to be cached by the service worker.
    1. a.

      The field name is an arbitrary title for the assetGroup (line 6). It uses an arbitrary name app, which is representative of primary application resources, like the JavaScript application bundles, stylesheets, index.html file, etc.

       
    2. b.
      The first few resource files between lines 9 and 12 include the following:
      1. i.

        A fav-icon that is shown along with the title of the application.

         
      2. ii.

        The index.html root HTML file for the Web Arcade application.

         
      3. iii.

        A web manifest configuration, which identifies the application as a progressive web app.

         
       
    3. c.

      Notice asterisks for lines 13 and 14, instructing how to cache all the JavaScript and CSS files (file names ending with js and css). See the “Pattern Match Resources to Cache” section to find out more about pattern matching resources to the cache.

       
  • Notice the install mode is prefetch on line 7. It enables the service worker to download all the assets at the beginning, regardless of whether they are utilized immediately or not. In an example, a few CSS or JS files may not be used on load. They may be used only after navigating to a different route or a page. However, prefetch install mode downloads the entire list of files.

    Considering these files constitute the application, it is appropriate to download the entire asset group at the beginning. Do not always use this install mode as it could cause a large number of network requests, slowing down the application and creating redundant network traffic.

  • Notice the second asset group between lines 18 and 28.
    1. a.

      The asset group is named assets (line 19). These are static resources typically including images, icons, fonts, etc.

       
    2. b.

      Resource files include all the files under the folder /assets. See line 24. Notice the usage of wildcard character asterisks. It refers to all the files and directories under the directory assets. Remember, Web Arcade has six die images for each side in the assets directory.

       
    3. c.

      See line 25. It instructs the app to cache all the files in the given list of extensions. The list of extensions indicates the font and image files.

       
  • Notice that install mode is lazy on line 20. It enables the service worker to download the files only when required. Unlike the first asset group, the service worker initiates the download of the files only when the application requests.

Note

Update mode in line 21 is used while updating a new version of the service worker for the application. Chapter 6 details an approach and a strategy for updating service workers.

Pattern Match Resources to Cache

In Listing 4-1, notice the resource file path in lines 8, 9, 22, and 23. They follow a pattern. As you can imagine, it is not possible to list all the resources (files and URLs) individually while developing the application. The list could be dynamic. Even if they are all known, it is a tedious job to list every single asset in a large project.

Use pattern matching to list the resources. The following are a few syntaxes to pattern match a link to a file or a URL:
  • Use two asterisks (**) to pattern match path segments. This is typically done to include all files and the child directories. In an example, the assets directory has another child directory called icons and a list of die images. See Figure 4-3. To include all the files and directories under assets, use /assets/**.

Figure 4-3

Assets directory

  • To include any file name or any number of characters, use a single asterisk (*). This matches zero or more characters. It does not include child directories.
    1. a.

      In an example, assets/* includes all the files in the directory assets. However, it does not include icons directory. To explicitly include the icons directory, use assets/icons/*, which includes all the files under the directory assets/icons/.

       
    2. b.

      In another example, imagine you need to include only the PNG files in the directory icons. You may use assets/icons/*.png. This will select all the icon files in Figure 4-3. If the directory has a file, say icon.jpeg, it will be excluded. This is hypothetical. Notice that lines 13 and 14 follow a similar pattern match that includes all .js (JavaScript) and .css (CSS) files.

       
    3. c.

      You can rewrite line 24 as shown in Listing 4-2.

       
// Comment- rewriting "/assets/**",
"files": [
  "/assets/*.png",
  "/assets/icons/*.png"
]
Listing 4-2

ngsw-config.json File

This is a specific instruction to include all the files with the extension .png under the directories /assets and /assets/icons. The original statement was generic, which included everything under the assets directory.

Why write a specific pattern similar to Listing 4-2, when you can include everything under the assets directory? Remember the install phase of a service worker. It installs either everything or nothing if the download of a single file fails. Even though this does not affect the functionality of the application, the service worker installation is postponed until the next time the application reloads. Such situations can occur on low-bandwidth networks. Configuring a generic pattern might include unnecessary files, which when they fail to download can cause problems with service worker installation. Hence, as much as you can, it is a good practice to be specific. However, if you know everything under the assets directory needs to be cached anyway, use the generic rule and simplify the configuration. More often than not, it depends on whether you use generic or specific patterns.

Note

While matching patterns, it is possible that two line items match a file. The service worker caches or excludes a file once it finds a match. It does not continue to look for the pattern in the next few items.

Imagine that /assets/** is on top in the array. It matches all files under assets, and the specific rule never runs. Hence, specify the generic rules toward the bottom of the list; specific rules should be at the beginning in the array.

So far, you have seen the pattern to include files. You may use the exclamation point (!) to pattern match excluding files. In an example, say you want to exclude caching all map files. A map file contains symbols for JavaScript code, which helps debug a minified version of the file. It is used in debugging and adds no value to the user to cache these files with a service worker. Hence, exclude map files with the pattern !/**/*.map.

Notice that you are selecting map files with *.map and excluding them with an exclamation point at the beginning.

Note

To pattern match a single character, use ?. It is not often that we can be so specific that we know the number of characters in a file or directory name. Hence, it is rarely used in ngsw-config.json.

Browser Support

Consider Figure 4-4, which depicts the browser support for a service worker and its features. Notice that the data is captured on the Mozilla.​org website, at https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorker. This is a reliable and open source platform for web technologies. Mozilla has been an advocate of the open web and has pioneered safe and free Internet technologies including the Firefox browser.
Figure 4-4

Service workers browser support

Note

CanIUse.com is another quality source of information for browser compatibility. As an alternative to Mozilla, please try https://caniuse.com/serviceworkers to learn more.

Summary

This chapter introduced service workers and the service worker lifecycle. They are a proxy running in the background on the browser. A service worker intercepts all the network requests from the application. Service workers cache static and dynamic resources and programmatically use the cached application scripts, images, data, etc. They enable an application to function even while disconnected from the network and on slow speed networks.

Exercise
  • Select and use a Google font in Web Arcade. Enable caching the font file with service workers. Do not copy the font to the project. Use the CDN location.

  • Imagine a production application’s releases are scheduled once a quarter. Regardless of how often the service worker features are updated, the icons, images, and stylesheets may change every quarter. Expire such resources’ cache every 12 weeks.

  • Explore and view all the service workers installed in your favorite browser.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.194.172