← All posts

Building a Progressive Web Application (PWA) with Angular Material and AWS Amplify.

Building a Progressive Web Application (PWA) with Angular Material and AWS Amplify.

https://itnext.io/part-1-building-a-progressive-web-application-pwa-with-angular-material-and-aws-amplify-5c741c957259?

This is the first of a series of posts outlining how to build a multi-platform Progressive Web Application (PWA) supporting mobile and desktop environments.

“PWAs combine the flexibility of the web with the experience of a native application.” — Wikipedia

A Progressive Web Application or PWA is a web application that is install-able on a (supported) mobile device via it’s web browser (Chrome or Safari). The key features and benefits are:

  • Reliability and Network Agnostic— Loads instantly and even in uncertain network conditions.
  • Install-able — Install-able on a mobile device and available via the devices home screen. A PWA feels like a native app on the device with an immersive user experience.
  • Search-able — Since a PWA is a web application and therefore lives on the internet. It is index-able by search engines and does not require an app store for installation.
  • Offline — With the help of app caching and service workers, a PWA is usable offline and in low connectivity environments. It also supports push notifications using the web Push API.

In this first article we will build a PWA that works with Chrome browser on Android and desktop (Mac, Windows, and Chrome OS) devices and Safari on iOS (11.3+) devices. The application will be built with Angular 7 and Angular Material. In terms of PWA functionality, there are a few caveats to consider specifically with iOS Safari (Webkit) compared to Android/Chrome.

On March 30th 2018 Apple released the iOS 11.3 update which included basic support for PWAs on iPhones and iPads. As of writing this article, the support is still basic and in development. The Webkit timeline outlines the status of key browser support including the Web application manifest and service workers.

  • Icon sizes in the manifest are not all compatible with iOS. You can use tags instead in the index.html file as we will do below to properly display the icon when adding to home screen in Safari.
  • Webkit support for the web application manifest is still in development as of the writing of this article. You can use the pwacompat.js; download it here. This will add rich PWA support for icons, home screen, splash screen etc. in many other browsers including Safari.
  • External links don’t work out-of-the-box in Safari. For something like sign in with google, you can set [ux_mode](https://developers.google.com/identity/sign-in/web/reference#gapiauth2clientconfig) to ‘redirect’ and for others you can directly set window.location however, keep in mind there is no back button displayed by Safari so there is then no way to effectively get back to your app once you leave.
  • There is currently no deep linking in Safari PWAs on iOS. In the web application manifest you can provide intent_filters along with a scope which will work only on Android/Chrome. See here for details.
  • Chrome provides an automatic popup prompting the user to install the PWA if you have everything wired up. Safari currently does not support this. You can make this work by detecting the platform and displaying a custom notification which will be described below.

Getting Started

We will bootstrap the application using the Angular CLI (v7) which will require Node.js (v8.11+). Then we will use the Angular Material UI library to style the user interface and make things responsive for both mobile and desktop. Finally, we will deploy the application to Amazon S3 and CloudFront using the AWS Amplify CLI.

Requirements

Source code is available on GitHub.

Let’s get started. Generate a new application with the Angular CLI. This will generate a boiler plate Angular project and install all required dependencies. It will also wire up routing and allow you to choose your preferred CSS framework. For this application we will use SCSS, but you can use whichever you prefer.

If you don’t have node.js (and npm) installed on your machine, follow the installation instructions for your operating system here.

$ npm install -g @angular/cli
$ ng new AngularPwaPostOne
$ ? Would you like to add Angular routing? Yes
$ ? Which stylesheet format would you like to use? SCSS

Add the angular material components to the application. This command will wire up the angular material and install the necessary dependencies.

$ cd AngularPwaPostOne
$ ng add @angular/material
$ ? Enter a prebuilt theme name, or "custom" for a custom theme: indigo-pink
$ ? Set up HammerJS for gesture recognition? Yes
$ ? Set up browser animations for Angular Material? Yes

This will bootstrap your application with dependencies for angular material, update configurations, and execute initialization code (see here for more details about what this does). Angular comes out of the box with Hammer.js which is (as their docs say) an “open-source library that can recognize gestures made by touch, mouse and pointerEvents. It doesn’t have any dependencies, and it’s small –only 7.34 kB minified + gzipped!”

The Angular animation system is built on CSS, which means you can animate any property that the browser considers animatable. This includes positions, sizes, transforms, colors, borders, and more. More details here.

Next you will generate a new Angular module that will load the angular material components. This helps separate the concern of loading and instantiating all of the material components while not polluting your application module.

This module will load all of them, however, you could also load only the components you want available to your module.

$ ng generate module material

Open up the src/app/material/material.module.ts file and update the contents with the contents of this gist. This module will load all of the material UI components.

In a production scenario you would probably want to trim this list down to only the components you are using which would decrease your overall JS bundle size.

Now, import the material module into your application module. Edit the app.module.ts file adding the bold sections:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MaterialModule } from './material/material.module';@NgModule({
  declarations: [ AppComponent ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    MaterialModule
  ],
  providers: [],
  bootstrap: [AppComponent]
});export class AppModule { }

Now we will create some routes and a new home component that will eventually be protected by an AuthGuard.

  • Replace the contents of src/app.component.html with this gist.
  • Replace the contents of src/app.component.ts with this gist.

Before we move forward, let’s outline what the deal is with the [brackets] (parenthesis) and (*asterisks) on the html elements found in the app.component.html file.

<app-element #myElement
 directiveName
 [prop]="value"
 [class.className]="cssClass"
 [style.fontSize]="50%"
 [style.stylePropertyName.px]="8"
 [attr.type]="(hide) ? 'password' : 'text'"
 [role.button]="{{myAriaRole}}"
 (click)="onClickEvent()">
</app-element>
  • directiveName — In structural directives the long form can only be applied to