Friday, October 23, 2020

Angular PWA with Service Worker

 AngularJS google Js Frame work can be easily integrated with PWA concept (again of Google) for allowing our application to run offline with Cache management.

In this blog we will try to understand how to integrate Service Worker concept in AngularJS project.

There are two possibilities
1- We want to crate a New Project
2- We already have an Existing Project in AJS and want to introduce PWA in it.

In both above example we will try to achieve the concept like Creating Angular PWA Application using the Angular CLI, Understanding and Updating (If project exist) How To Add Angular PWA Support Manually,Angular Service Worker runtime caching mechanism, Running and Understanding the PWA Production Build,Launching an Angular PWA in Production Mode, Deploying a new Application Version, Understanding Version Management and One-Click Install with the App Manifest

Lets first look in to first aspect i.e.

1- We want to crate a New Project

The first step to create an Angular PWA is to upgrade the Angular CLI to the latest version:

npm install -g @angular/cli@latest

if you want to use the with latest features then below command

npm install -g @angular/cli@next

Execute below command to create a new AJS project with PWA feature.

ng new angular-pwa-app

now lets run the created AJs project using below command

PS C:\Visual_Source_Code_WorkSpace_AngularJS\AngularJS-PWA-NewProject-ServiceWorker\angular-pwa-app> ng serve

Also as we generally run our project in

ng serve

but for PWA we are not going to use this command as ng serve run the applicaiton in cache and PWA will not work properly. For that we are going to use annother light weight server called as http-server you can install the same using below command.

npm i http-server

Now we are ready to convert our existing AJs project into PWA. We can do the same using below command to do the same.

ng add @angular/pwa –project [name of project]

i.e. PS C:\Visual_Source_Code_WorkSpace_AngularJS\AngularJS-PWA-NewProject-ServiceWorker\angular-pwa-app> ng add @angular/pwa –project angular-pwa-app

This command do follwing changes

1- Change 1: ‘@angular/pwa’ and ‘@angular/service-worker’ has now been added to package.json.

Note: If you did not find @angular/pwa in package.json dependencies then execute belwo command and recheck the same.

npm install @angular/pwa

There’s one other flag that is now enabled in you angular-cli.json(angular 2 and above) or angular.json(angular 6 and above) named “serviceworker” which is set to ‘true’.

serviceWorker: true flag make an application progressive by doing following below given jobs.
‘- It creates a file called ngsw-worker.js
‘- It captures run time config such us bundled files, images etc in to your ngsw.json

2- Change 2:
In our root module i.e. app.module.ts we can see CLI has included “ServiceWorkerModule”

ServiceWorkerModule.register(‘/ngsw-worker.js’, { enabled: environment.production })

“serviceworker: true” will create ngsw-worker.js while building the application. This is the reason we reference ‘ngsw-worker.js’ in ServiceWorkerModule registry.

Its also to be noted that enable property will set to true when the environment.production is set to true in your environment config file environment.prod.ts

i.e, The service worker module registers only and only if it is a production build.

In normal build environment.ts i.e. no prod build this flag is set to false.

The main task of this module is to register the angular service worker java script in the browser( if supported).

3- Change 3:
In index.html follwing line is added

i.e. it has the reference to the ‘manifest.json’ file which is very much essential when your wanted to add the app in to your home screen.

This file manifest.json has to be added in the assets folder in angular-cli.json(angular 2 and above) or angular.json(angular 6 and above) file.

Now lets build and run the application using below commands:-
PS C:\Visual_Source_Code_WorkSpace_AngularJS\AngularJS-PWA-NewProject-ServiceWorker\angular-pwa-app> ng build –prod

now we can see the dist folder and inside that dist folder we have ngsw-worker.js created by cli for us.

Note:- We never update this file with our hand. It get updated automatically when ever you run ng build –prod command.

Now lets go inside out dist\angular-pwa-app folder and execute our project with http-server command given below

http-server -p 8081

Note:- If you are not able to open the application using above command follow below pathname

cd dist
cd project_name
npx http-server

i.e. run this command
npx http-server -p 8181

Now you might be knowing the thum rule of pwa i.e. your application can only accomodate PWA feature if you are running on HTTPS or it is on local host.

Now as we are running our application using IP address from http-server command

http://192.168.99.1:8181

we will not be able to see the service worker registration on chrome application tab alo no menifest entry as shown below

Run the browser with this url

http://loclahost:8181

Now lets go offline and refresh and check if we are able to run the application

We are successful in installing/integrating PWA in our AJS project.

Now lets make some changes in out project and add the functionality like

1- Dynamic Caching
For this concept we are going to call a JSON REST W/SAAJMetaFactory
for that we need to install below package
PS C:\Visual_Source_Code_WorkSpace_AngularJS\AngularJS-PWA-NewProject-ServiceWorker\angular-pwa-app> npm i @angular/http

Also make some change in the following files

1- app.component.html

<app-post *ngFor="let post of posts" [content]="post.body" [title]="post.title"></app-post>

2- Add HttpClientModule in app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ServiceWorkerModule } from '@angular/service-worker';
import { environment } from '../environments/environment';
import { HttpClientModule } from '@angular/common/http';
import { PostComponent } from './post/post.component';
@NgModule({
declarations: [
AppComponent,
PostComponent
],
imports: [
BrowserModule,
AppRoutingModule,
ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production }),
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

3- app.component.ts

import { Component, OnInit } from '@angular/core';
import { Post } from './post.model';
import { HttpClient} from '@angular/common/http';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'angular-pwa-app';
posts: Post[] = [];
constructor(private http: HttpClient) {}
ngOnInit() {
this.http
.get('https://jsonplaceholder.typicode.com/posts')
.subscribe(fetchedPosts => (this.posts = fetchedPosts));
}
}

4- create this file post.model.ts

export interface Post {
title: string;
body: string;
id: number;
userId: number;
}


5- Create post.component.html

{{ title }}
{{ content }}

6- post.component.css

article {
padding: 1rem;
margin: 1rem auto;
box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.5);
font-family: 'Oswald', sans-serif;
width: 30rem;
max-width: 80%;
}
h1 {
font-family: inherit;
font-weight: bold;
}

7- post.component.ts

import { Component, Input } from '@angular/core';
@Component({
selector: 'app-post',
templateUrl: './post.component.html',
styleUrls: ['./post.component.css']
})
export class PostComponent {
@Input() title: string;
@Input() content: string;
}

Now run following command this will refresh the code in our dist folder
PS C:\Visual_Source_Code_WorkSpace_AngularJS\AngularJS-PWA-NewProject-ServiceWorker\angular-pwa-app> ng build –prod

And finally run this command and run your application and check the out put.

Now lets go offline and make sure to go offline not by using check box of chrome .. as it very its behaviour..go offline by clicking wifi offline.

and check if you are able to see the REST call data on the screen and you will find you can see only hard code cache value and not the REST call data as we did not have yet done the cache of dynamic data lets do the same now.

As you can see we are able to see the static text angular-pwa-app but not the dynamic REST content and to do this we need to modified ngsw-config.json for that

"dataGroups": [
{
"name" :"postscalldata",
"urls": [
"https://jsonplaceholder.typicode.com/posts"
],
"cacheConfig": {
"maxSize": 5,
"maxAge": "10m",
"strategy": "freshness"
}
}
]

There are many option you can used
maxSize :- Will inform how many response we will cash and not the data
maxAge:- The age we need to keep the cache i.e. 5h , 10m or 1d
timeout:- If we are waiting for the response for 10 sec and if the response did not come then take the value from Cache.
Freshness:- Use cash if offline or take the data from betwork,
Performance:- It take maxAge account and decide weather to go to the back end and fetch the value or show

Now lets again run

ng build –prod

and

npx http-server -p 8181

and check now if we are able to access the data offline.

You can download the code from
https://github.com/shdhumale/AngularJS-PWA-NewProject-ServiceWorker.git

No comments: