Tutorial: How to Build a Progressive Web App (PWA)
Tutorial: How to Build a Progressive Web App (PWA)
In this article, we discuss some basics behind building PWAs and then provide a comprehensive tutorial on creating your first one.
Join the DZone community and get the full member experience.Join For Free
You need a native app. That's what we've been told repeatedly since Apple first announced the iPhone App Store. And perhaps you do. Native apps can make sense, depending on an organization's size and needs.
But what about potential customers who don't have your app? Or current customers on a desktop computer? What about people with limited space on their phones who delete apps to make room for other things? What is their experience like?
This is where Progressive Web Apps (sometimes referred to as PWAs) shine. They combine the best features of the web with capabilities previously only available to native apps. Progressive Web Apps can be launched from an icon on the home screen or in response to a push notification. They load nearly instantaneously and can be built to work offline.
Best of all, Progressive Web Apps simply work. They are an enhancement to your website. No one needs to install anything to use a Progressive Web App. The first time someone visits your website, the features of a PWA are available immediately — no app stores (unless you want them). No gatekeepers. No barriers.
You may also like: Developing a PWA Using Angular 7.
To start with this tutorial you must install the following:
Stable node version 8.9 or higher (https: // nodejs.org/en/download/).
As a starting point for the tutorial, clone this Github repository:
then, move to the following directory:
and install the dependencies through:
Open your app on: http:// localhost:8080
What Are the Technical Components of a PWA?
Manifest file, the Service Worker, and the PWA must run under https.
The Manifest file is a configuration JSON file that contains the information from your PWA, such as the icon that appears on the home screen when it is installed, the short name of the web app, or the background color. If the Manifest file is present, Chrome automatically activates the banner for installing the web app (the "Add to Home Screen" button). If the user agrees, the icon will be added to the home screen, and the PWA will be installed.
Create a Manifest.json
A Manifest.json file for a PWA looks like this:
Tell the Browser About Your Manifest
Create a Manifest.json file at the same level as your index.html file.
When you have created the Manifest, add a link-tag to your index.html (between the other links tags).
You must at least specify the property, short_name or name. Short_name is used on the user's home screen. Name is used in the app's install prompt. When a user adds your PWA to their home screen, you can define a set of icons that the browser should use.
These icons are used in places, such as the home screen and the app launcher. The start_url property tells the browser where it should start the application. The scope defines the set of URLs that the browser considers to be within your app and is used to decide when the user has left the app and should be bounced back out to a browser tab. Your start_url property must be within the scope. The display property indicates the following display modes:
- Fullscreen: all available space is used for the app.
- Stand-alone: the application has the look and feel of a stand-alone application.
The background_color property is used on the splash screen when the application is started.
From this point, the "Add to Home Screen" button does not work yet. But, you can already experiment with the Manifest file. There are currently various tools with which you can generate your Manifest file with, such as https://app-Manifest.firebaseapp.com/..
Add the Manifest to Your Application
Generate your own Manifest and place it at the same level as the index.html file. Check your Chrome Developer Tools and see if your Manifest is active. Right-click on the homepage of the Progressive Selfies App and select "Inspect". Select the "Application" tab and choose "Manifest". Restart the server with
npm start if necessary.
What Is a Service Worker?
The reason this is such an exciting API is that it allows you to support offline experiences by taking advantage of cache, giving developers complete control over a user's experience.
The Service Worker LifecycleWith Service Workers, the following steps are taken for the basic setting:
- Register your SW. You must first register it. If the SW is registered, the browser automatically starts the installation based on an install event.
- When the SW is installed, it receives an activate event. This activation event can be used to clean up resources used in earlier versions of an SW.
For the SW, create an empty file named sw.js at the same level as your index.html file. And in the index.html file, add a base tag (between the other links tags in the <head> section). This is the base URL for all your relative links in your app:
Finally, add the code below in src/js/app.js to register the SW. This code is activated during the "loading" of the first page.
You can now check whether an SW is enabled in the Chrome Developer Tools in the Application -> Service Workers tab. Refresh the page for this!
Why Can't I Register my Service Worker?
This could happen for a couple of reasons:
- Your app could not be running under HTTPS. During development, you can use the SW via localhost. But, if you deploy it on a site, then you need an HTTPS setup.
- The path of the SW is not correct.
- Update on reload must be checked during development!
Service Worker Events
In addition to install and activate, we have a messagingevent. This event takes place when a message is received from another script in the web app. The fetchevent is triggered when a page from your site requires a network resource. It can be a new page, a JSON API, an image, a CSS file, etc.
Add the following code to your SW to listen to the lifecycle events (install and activate):
install callback is calling the
skipWaiting() function to trigger the
activate event and tell the Service Worker to start working immediately without waiting for the user to navigate or reload the page.
skipWaiting() function forces the waiting Service Worker to become the active Service Worker. The
self.skipWaiting() function can also be used with the
self.clients.claim() function to ensure that updates to the underlying Service Worker take effect immediately.
In this context, the self-property represents the window object (ie your browser window).
Add to Home Screen Button
The "Add to Home Screen button" allows a user to install the PWA on their device. In order to actually install the PWA with this button, you must define a fetch event handler in the SW. Let's fix that in the sw.js.
Check Update on reload, Unregister your SW in Chrome Dev tools, and refresh your screen. Go to your PWA (on localhost:8080), click the "Customize button" in Chrome, and select: Install Progressive Selfies ....
After this, the "install banner" is shown.
Service Worker CachingThe power of Service Workers lies in their ability to intercept HTTP requests. In this step, we use this option to intercept HTTP requests and responses to provide users with a lightning-fast response directly from the cache.
Precaching During Service Worker Installation
When a user visits your website for the first time, the SW starts to install itself. During this installation phase, you can fill the cache with all pages, scripts, and styling files that the PWA uses. Complete the sw.js file as follows:
This code uses the install event and adds an array of
URLS_TO_PRECACHE files at this stage. You can see that once the cache is open (
caches.open), you can then add files using the
The install event calls the
self.skipWaiting() to activate the SW directly. If all files have been successfully cached, the SW will be installed. If one of the files cannot be downloaded, the installation step fails. In the Chrome Developer Tools, you can check whether the cache (in the Cache Storage) is filled with the static files from the
But, if you look in the
Network tab (even after a refresh) the files are still fetched over the network. The reason is that the cache is primed and ready to go, but we are not reading assets from it. In order to do that we need to add the code in the next listing to our Service Worker in order to start listening to the existing fetch event.
We are checking if the incoming URL matches anything that might exist in our current cache using the
caches.match() function. If it does, we return that cached resource, but if the resource doesn't exist in the cache, we continue as normal and fetch the requested resource.
After the Service Worker installs and activates, refresh the page and check the
Network tab again. The Service Worker will now intercept the HTTP request and load the appropriate resources instantly from the cache instead of making a network request to the server.
Now, if we set
Offline mode in the
Network tab our cached app will look like this:
The Background Fetch API is a SW background feature that makes it possible to download large files, movies, podcasts, etc. in the background. During the fetch/transfer, your user can choose to close the tab or even close the entire browser.
This will not stop the transfer. After the browser is opened again, the transfer will resume. This API can also handle poor accessibility. The progress of the transfer can be shown to the user, and the user can cancel or pause this process.
Finally, your PWA has access to the data/sources that have been retrieved.
Experimental Web Platform Features
Background Fetch works if you have enabled " Experimental Web Platform features" via the URL:
Below is an example of how to implement such a Background Fetch.
Add this button with an ID of "bgFetchButton" in your index.html file (among the other buttons in the header).
Then, add the code for executing a Background Fetch in your app.js in the load event handler:
The code above performs a Background Fetch under the following conditions:
- The user clicks on the button with the ID of
bgFetchButton(the onClick event will go off)
- The SW must be registered.
This check and the Background Fetch takes place within an async function because this process must be performed asynchronously without blocking the user.
Fill the cache in sw.js
This code consists of the following steps:
- Once the Background Fetch retrieval is complete, your SW will receive the Background Fetch success event.
- Create and open a new cache with the same name as the registration.id.
- Get all records through
- Build an array in an asynchronous way with promises by going through the records. Wait until the records with responses are ready and then save these responses in the cache with
cache.put()(see the Cache Storage in the Application tab).
- Finally, execute all the promises, through
After this introduction, you can continue with an extensive tutorial that you can find in: https://github.com/petereijgermans11/progressive-web-app/tree /master/pwa-workshop. This tutorial focuses on issues such as generating your SW through Workbox, Caching strategies, Web Push Notifications, and Background synchronization with an IndexedDB API and various other new Web APIs.
See also my next article. In this article I will discuss some advanced PWA features that provide access to your hardware APIs, like: Media Capture API, Geolocation API and the Background Sync API.
Follow or like me on twitter https://twitter.com/EijgermansPeter
Opinions expressed by DZone contributors are their own.