Make Angular run in Offline mode - PWA

cover-photo

Make Angular run in Offline mode - PWA

blog-photo

In this article you will learn about how to make your angular app run even if there is no Internet (angular pwa offline). For this we are going to use Service Workers in Angular and apply caching method.

Service workers augment the traditional web deployment model and empower applications to deliver a user experience with the reliability and performance on par with natively-installed code. Adding a service worker to an Angular application is one of the steps for turning an application into a Progressive Web App also known as a PWA (angular pwa offline) and make angular run in offline mode,

So in short Service Workers is a script which intercepts all your network calls and cache the their responses in local cache system. You can cache API call responses and even your resource files too such as images etc.

Adding a service worker to your project

ng add @angular/pwa --project *project-name*

By running this cli command the angular does following changes

  1. Adds the @angular/service-worker package to your project.
  2. Enables service worker build support in the CLI.
  3. Imports and registers the service worker in the app module.
  4. Updates the index.html file: (Includes a link to add the manifest.webmanifest file, Adds meta tags for theme-color).
  5. Installs icon files to support the installed Progressive Web App (PWA).
  6. Creates the service worker configuration file called ngsw-config.json, which specifies the caching behaviors and other settings.


The main file to set configuration of which resources are to be cached you have to check the ngsw-config.json file.

{
  "$schema": "./node_modules/@angular/service-worker/config/schema.json",
  "index": "/index.html",
  "assetGroups": [
    {
      "name": "app",
      "installMode": "prefetch",
      "resources": {
        "files": [
          "/favicon.ico",
          "/index.html",
          "/manifest.webmanifest",
          "/*.css",
          "/*.js"
        ]
      }
    }, {
      "name": "assets",
      "installMode": "lazy",
      "updateMode": "prefetch",
      "resources": {
        "files": [
          "/assets/**",
          "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
        ]
      }
    }
  ]
}

As you can see in the above file angular by default adds some resources to this file which should be cached in the "assetGroups" object.

No we can go ahead and check service workers in action to do this first we have to create a Build of our angular project

//step1 build angular project
ng build --prod

//step2 server the build files using http-server
http-server dist/<project-name> -o

//step 2 Alternate method: Or go in your dist folder from your directory and run this command
http-server -o

Make sure you have installed http-server on your system if not use this command to install it .

//install http-sever
npm i http-server


Note: If you are not using HTTPS, the service worker will only be registered when accessing the app on localhost.

Now once your app is completely loaded in the Browser go to your developer tools and in newtork tab switch to offline mode as showed in image below.

blog-photo

Switching the offline method it switches off the internet access to your site in chrome. Now refresh your page and check network tab again you would see that the resources are loaded from the local cache and it will show as loaded from service worker check the image below, this verifies that your service workers are working as expected.

blog-photo

Now to Cache the API calls made by your application you have to mention it in ngsw-config.json file by adding another array as "dataGroups" after the "assetGroups" array.

"assetGroups": [{...}],
"dataGroups": [
      {
        "name": "restapiexample dummuy API",
        "urls": ["https://reqres.in/api/users"],
        "cacheConfig": {
          "strategy": "freshness",
          "maxSize": 20,
          "maxAge": "12h",
          "timeout": "5s"
        }
      }
]

//name : Any name .
//urls : Array of API urls in string.
//strategy :  'freshness' | 'performance' 
//maxSize : The maximum number of entries, or responses, in the cache.
//maxAge : '1d' | '1h' | '1m' | '1s' | '1u' 
//timeout : '1d' | '1h' | '1m' | '1s' | '1u' 

In service worker Angular also provides a service to check whether there is a fresh version of application and you should refresh the application to replace the cached version stored in your browser cache or you can even notify the user like "fresh content available please refresh".

//import service
import { SwUpdate } from '@angular/service-worker';

//inject in constructor and use 
constructor(updates: SwUpdate) {
    updates.available.subscribe(event => {
      console.log('current version is', event.current);
      console.log('available version is', event.available);
      console.log('old version was', event.previous);
      console.log('new version is', event.current); 
    });
  } 


Note: Make sure the API or network calls you make user Https because Service Workers doesn't work on Http protocols.

Some of the most common questions related to Angular Service Workers


Angular pwa not working offline

Some of the developers face problem of angular pwa not working offline to fix this firstly you have to check your build files inside dist folder and look for ngsw-manifest.json, sw-register.b73048fe3d9f8a1e7ae5.bundle.js and worker-basic.min.js files. If you don't find these files it means your service worker was not registered correctly. Secondly you have to check your Network Environment, service workers doesn't work in http it requires https so if you don't have a SSL certificate your service worker won't work.


Angular service worker not caching API

When you add angular pwa to your application you get a  ngsw-config.json file it consists config for caching the static resources in "assetsGroups" Object. To enable caching of Api in angular service worker you have to set "dataGroups" Object inside ngsw-config.json file.

"dataGroups": [
      {
        "name": "restapiexample dummuy API",
        "urls": ["https://reqres.in/api/users"],
        "cacheConfig": {
          "strategy": "freshness",
          "maxSize": 20,
          "maxAge": "12h",
          "timeout": "5s"
        }
      }
]

How to create a new project in angular offline?

To create new project in angular offline mode use --skip-install followed by ng new --projectName command.

ng new yourProject --skip-install


Angular offline storage

When you are in offline mode no requests will be made to the database as API calls need internet connection to work. You can although cache the API requests using angular service worker which will efficiently deliver the results stored in cache when there is no Internet Connection. Also if you want to save some data temporarily you could still use the LocalStorage. LocalStorage is an default HTML API which stores data locally in your Browser.


Angular service worker cache API

To enable caching of Api in angular service worker you have to set "dataGroups" Object inside ngsw-config.json file.

"dataGroups": [
      {
        "name": "restapiexample dummuy API",
        "urls": ["https://reqres.in/api/users"],
        "cacheConfig": {
          "strategy": "freshness",
          "maxSize": 20,
          "maxAge": "12h",
          "timeout": "5s"
        }
      }
]

Ngsw-worker js not found

If your Ngsw-worker js file is not generate on prod build make sure you serviceWorker is set to true in angular-cli.json.

"build": {
    "configurations": {
        "production": {
            "serviceWorker": true
        }
    }
}


Angular service worker update cache

If you want data to be updated as soon as there's new data available you can set cacheConfig strategy to freshness in ngsw-config.json file.

"dataGroups": [
      {
        "name": "restapiexample dummuy API",
        "urls": ["https://reqres.in/api/users"],
        "cacheConfig": {
          "strategy": "freshness",
          "maxSize": 20,
          "maxAge": "12h",
          "timeout": "5s"
        }
      }
]


Angular service worker exclude url

To exclude url in service worker you just have to skip that url from urls array in "dataGroups" of  ngsw-config.json file. You should only specify the urls which you want to be cached.


Hope you find this post useful.


Happy Coding!