Rocking the web with PWA
Progressive Web Apps + Angular = 💖
This article has been written based on my talk about PWAs in Angular MedellÃn, You can find the slides here.
To start we need to know what Progressive Web App is, here a bit of history:
Back in 2015 Alex Rusell and Frances Berriman, from the Google Chrome team, had a dinner and while they ate they started a discussion about what attributes should have a non-hybrid app to behave as a native app but inside the browser, they gave it the name ‘Progressive Open Web Apps’ then both came around to just ‘Progressive Web Apps’.
I also googled about PWA and found this:
I like to summarize PWAs as a combination of the best of the web and the best of the apps put together and delivering a great user experience.
In Google I/O 2018, they adopted the term ‘FIRE’ as the key to create a successful PWA because they must be Fast, Integrated, Reliable and Engaging.
Fast — Decrease the load time of the app.
Integrated — Feels natural in users device and takes advantage of device’s capabilities.
Reliable — No matter the network conditions, the app has to work.
Engaging — User must love to use the app.
To achieve it you need to have in mind these three concepts:
- manifest.json
- Service Workers
- User experience
1. Manifest.json
Web app manifest is part of a collection of technologies needed in progressive web apps. It is a JSON file that tells the browser basic metadata about your site and the way you want your app to behave when it is installed on the user device.
- short_name: Will be the name displayed when the app is installed.
- theme_color: This will be the color in the notification area.
- background_color , name and icons: will be used to create the splash screen at the bootstrap time.
- display: Preferred display mode of the app.
- scope: Defines the navigation scope of the app. If the user navigates outside the scope it returns to a normal web page 2inside a browser.
2. Service Workers
This could be the more extensive topic doing PWAs due to all the features a service worker can handle.
A service worker is a script that your browser runs in the background, separate from a web page, opening the door to features that don’t need a web page or user interaction.
Nowadays service workers can handle features like ‘push notifications’, ‘background sync’ and have a special ability to intercept and handle network requests acting as a network proxy in the client.
2.1 Prerequisites:
- Browser must support service workers
- Your site must be served over HTTPS to avoid a man-in-the-middle attack.
2.2 Lifecycle
Up next you will see the entire service worker lifecycle and an explanation of every state.
- Parsed
This is the first step before try to register a service worker, the user agent parses the script and obtains the entry point, if parsing is successful you will have access to the Registration object that contains information about the state of the service worker.
- Installing
Once the script has been parsed, the user agent will attempt to install it and move the state to installing. Here the service worker start to catch static files. If the installing step fails the service worker becomes redundant.
- Installed/waiting
The installation was successful, service worker state moves to installed (or waiting). At this point the service worker is valid but not yet available, it means the service worker still does’t have control over the document but is waiting to have it.
- Activating
Activating state will be triggered for a waiting service worker in one of the following scenarios:
- There is no active service worker already
- The user navigates away form the page, releasing previous active service worker
- A specified period of time has passed and the previous active service worker was released.
- the skipWaiting() method is called in the script.
If the activation is not successful, the service worker becomes redundant.
- Activated
If the activation was successful the service worker state is active, in this state the service worker have full control of the document and can handle functional events.
- Redundant
If the installing event or the activating event fails, the previous service worker keeps control of the document. If there is a new active service worker, the service worker state is redundant and the new service worker takes control over the document.
Service worker is attached to the scope where the file lies, e.g. sw path is app/dashboard/sw.js everything inside dashboard folder will be in the service worker scope, but if the path is app/login everything inside login folder is unreachable for the service worker.
— One of the biggest benefits of having a service worker is the capability to work offline, you just create an app shell with the core of your application and all the cached files.
3. User experience
Do not force your users to make an action they don’t want to perform. Prompting users to allow permissions for notifications, device storage, camera… after bootstrap will turn down their experience using your app. Always wait for user’s actions to take advantage of the features the browser gives you to make the experience more ‘native’. Prompt permissions after user toggles to subscribe to notifications, or ask for camera access after the user tries to use that feature inside your app. Besides all of this, make an entire experience the whole navigation in your app, use beautiful transitions, accessible menus, etc. You might know what’s the best way to use your app.
Angular and PWA
Angular provide schematics for you to easily install the Angular package that allows you to start with basic settings for a PWA in your project.
With the command ng add @angular/pwa
you will install a ServiceWorkerModule
, app.module.ts
will be updated to use the service worker module, a brand new manifest.json
will be created ready to go,index.html
will be updated to use the manifest file, an ngsw-config.json
file will be created and your angular.json
will get updated to use this new files.
ngsw-config.json
This configuration file contains the information that use the service worker to know at runtime which files are needed to cache, and the way to load these files: prefetch
to load it proactively or lazy
to load it as is needed; service worker also store the files in Cache Storage.
After create your production artifact yarn build --prod
this config file will create ngsw.json
file with the cache strategy you want to follow. This file have a hash table, service worker will check that table and compare it with the cached one, if exist. If something changes, the service worker will trigger an event because there is a new version of your app.
Let’s see it in action
You can use http-server
, an npm package that set up a local server in your distribution directory to emulate production environment, so let’s go into the distribution folder cd dist/[project]
and run http-server -c-1
. (The flag -c-1
will disable server cache) we just want to see the service worker in action.
On first load, everything looks as usual, let’s take a look to the network calls
And a few seconds later you will see the service worker doing its job
Service worker is now controlling the web site, files are stored in browser cache following your cache strategy. You can verify service worker activation in Application tab in ‘Chrome Dev Tools’
Next time you reload your site you will see all network calls intercepted an served from service worker.
Your PWA is alive!!
Wrapping up
From my point of view, PWAs are applications conceived to deliver a great user experience, is not just about working offline, receiving push notifications or the app-like feeling. Work hard with the UX/UI team, think about usability, accessibility, find the best way to navigate through your site, make the loading time faster… Always remember the goal of PWA is make user loves your application.
Success Stories
Here you can find a compilation of success stories, companies that turned their development process to PWA and now are touching the sky.