Build a Progressive Web App (PWA) With Ionic 4

Ionic 4 is a step forward for Progressive Web Apps. It’s clear to me that the Ionic Framework team is doing a great job positioning themselves as the Framework of choice to build PWAs.

In this ionic 4 tutorial I will show you what are Progressive Web Apps, why you should definitely consider them for your next project, and also how easy is to build a feature complete PWA with Ionic 4.

This post is part of the “Mastering Ionic 4” series which deep dives into Ionic 4 more advanced stuff. Don’t be afraid, if you are new to Ionic 4, I strongly recommend you to first read our introduction to ionic 4 previous tutorial.

In this series of posts we have already talked about Web Components, Shadow DOM, CSS 4 Variables, and Stencil. To complete the in-depth analysis of the new Ionic 4, besides talking everything about Progressive Web Apps in this post, we will also be addressing the new Ionic 4 Navigation using Angular Router in our third and final post.

At IonicThemes we are big fans of Learning by example, that’s why all our ionic tutorials include a complete and free ionic code example that you can reuse in your ionic projects. We strive to create the best content for Ionic Framework, both tutorials and templates to help the Ionic community succeed. We work towards empowering developers to achieve a free life through coding. That’s what motivates us at IonicThemes everyday.

Check out our detailed and professional templates crafted with love and dedication to help you create better apps and supercharge your productivity.

All in with Progressive Web Apps

What is a Progressive Web App?

Progressive Web Apps are a synergy of the very best between Web and Native worlds.

PWAs are web applications that load like regular web pages or websites but can offer the user functionalities traditionally available only to native mobile applications such as push notifications, working offline, and device hardware access.

PWAs are useful to users from the very first visit in a browser tab as there’s no need to go to the App Store and install the app.

The initial 'download' of a PWA is minimal (a few kb's with just the assets needed for the basic first interaction with the app) in contrast with native apps where you download the full app upfront (quite some MB of assets).

It’s worth mentioning that PWAs aren't a new framework or technology. They are a set of best practices to make a web application function similar to a desktop or mobile application. The ideal situation would be to have an experience so seamless and uniform that the user is unable to tell the difference between a Progressive Web App and a native mobile app.

PWAs combine the open standards of the web offered by modern browsers to provide rich mobile experiences.

Instant or Progressive Web Apps are known for loading in record time even if the network is spotty since they use cache strategies. To keep customers engaged, they provide push notifications and have icons on the home screen, while still loading as a top level, full-screen experience.

The advantage of this new approach is that it lowers the cost of customer acquisition, while improving the conversion rates. It’s a great tool for onboarding new customers, since the discoverability of the web makes them perfect for its advertising and social media communication purposes.

The Web is for audience reach and native apps are for rich experiences. Both are strategic. Both are valuable. So when it comes to mobile, it’s not Web vs. Native. It’s both.

Why do we need Progressive Web Apps?

To understand why we need progressive web apps, let’s first talk about some of the biggest challenges we are facing today with native and responsive web apps:

Internet speed: depending on where you live internet may be a nightmare. You may have not realized this, but 60% of the world’s population is still using 2G internet.

Slow website load: Do you know how long a user waits to close a website if it’s too slow? Only three seconds! 53% of users abandon a website if it loads too slow.

High friction: People don’t want to install native apps. An average user installs 0 applications in a month. Contrast this with how many new web sites they visit each month. Also think about how many apps you downloaded and eventually ended up using just once or very few times?

User engagement: Responsive mobile web sites have much more reach than native apps, however they lack basic functionalities like push notifications and offline support. That causes that most of the users of responsive web sites are not actively engaged compared to native apps engagement levels.

PWAs help solving these problems. Let’s go through the main benefits of using progressive web apps.

Main benefits of using PWAs

Benefits first time seen on a web app:

  • Web app install banner prompt
  • Launch from user’s home screen
  • Full screen browser mode
  • Push notifications for web app
Build a PWA with Ionic 4

CONNECTIVITY INDEPENDENT - Enhanced with service workers to work offline or on low-quality networks.

APP LIKE - Feels like an app to the user with app-style interactions and navigation.

FRESH - Always up-to-date thanks to the service worker update process.

DISCOVERABLE - Due to the web nature of Progressive Web Apps, search engines are able to find them! This is super important for SEO purposes.

Re-ENGANGABLE - Makes re-engagement easy through features like push notifications.

INSTALLABLE - Allows users to "keep" apps they find most useful on their home screen without the hassle of an app store middleman.

LINKABLE - Easily shareable via URLs.

Integrated and Engaging User Experience

PWAs feel and behave like native apps. They sit in a user’s home screen, send push notifications like native apps, and have access to some device functionalities like native apps. The experience feels seamless and integrated. Because we can send notifications to a user, we can really drive the engagement up by keeping the user notified and engaged with the app like we do in native apps.

Engaging is not only about push notifications, in my opinion is paramount to have an unobtrusive way for users to try the service and taste the potential value of your product early on.

In Twitter’s case, when someone shares a link of a tweet and people click on it, it will open that tweet’s conversation. Browsing around and feeling the experience of Twitter without installing anything is a good way to showcase the value of Twitter without any hurdles. You can even go a step further by embracing PWA capabilities and enable users to also get a notification every time someone mentions your account. Just exactly like the Twitter native mobile app.

Following the Progressive Web App (PWA) pattern to provide native experience on mobile phones through web standards, people can use their favourite services directly on their phones without downloading any native app.

If you want to start creating your Ionic Framework app but don’t know how to start, I suggest your to try Ion2FullApp ELITE. It’s an ionic starter app that you can use to jump start your Ionic app development and save yourself hundreds of hours of design and development.

It includes more than 50 carefully designed views and components and the most required functionalities such as: Wordpress integration, Social login integrations, Firebase integration, Geolocation and maps, Forms and validations and so much more!


Cheaper and Improved User Acquisition

The open nature and discoverability of the web compared to app stores translates into a more democratic and organic way of finding content, and this translates to both user reach, user experience friction, and user acquisition costs.

Convenience is a key factor when talking about user acquisition. Some industries like gaming, retail, content publishing and other “in-the-moment” services rely on the web and SEO for driving traffic and user acquisition. By adding PWAs to their mobile strategy hey can benefit greatly. Let’s imagine for a moment that you’re looking for a quick dinner delivery from your favorite restaurant. You go and search for its website and look to place an order, but you are pushed to download an app in order to be able to place the order. What would you do? Do you download it? Do you call the restaurant? Or do you abandon the idea all together?

Uber pictured this and put a lot of advertising banners around airports featuring a PWA url. This way when a tourist want to use Uber for the first time, they can avoid going through the Play Store or App Store to install the app first. Using the Uber Progressive Web App is really simple, people just have to open a URL and use Uber services directly without having to install anything.

Friction is something you should be aware of, it’s important to understand that pushing people to the app store isn’t the silver bullet some brands think it is. Asking users to give up valuable space on their phone for an app they may never open often can hurt customer relationships rather than make them stronger - and could risk losing visitors altogether.

Sometimes it doesn’t make sense to download an app before it proves valuable to you. Let’s see some examples so you can get what I mean:

  • Booking transport, either bus, train, or taxi. When you arrive at a new city you want a quick and light solution for transportation.
  • Event information for schedule, speaker list, and venue map. Doesn’t make sense to ask the user to download an app just to use it for a couple hours.
  • Online shops, where brands usually promote the products through social media. Would users convert if you add an extra step to the funnel by requiring them to download your app from the app store?
  • Queue system, for bank, hospital, etc. Imagine every time you go to a new place that needs you to queue and you need to download an app just to get the queue number. Complete nonsense.
Brands are seeking to overcome this user acquisition challenge, and Progressive Web Apps are becoming the way to go.

Better Performance, Conversion and Engagement

PWAs provide experiences that are consistently fast. From the moment a user downloads an app to the moment they start interacting with it, everything happens really fast. Because they leverage cache, repeated uses of the app don’t have to hit the network resulting in an even faster experience.

PWA are better for your business

Overall I’m seeing a vast amount of scenarios where Progressive Web Apps outperforme their native and mobile web counterparts. I find PWAStats a great resource to articulate this claiming.

Take the experience and results top brands are having with their PWA endeavors.

  • Tinder
    • Tinder cut load times from 11.91 seconds to 4.69 seconds with their new PWA. The PWA is 90% smaller than Tinder’s native Android app. User engagement is up across the board on the PWA.
  • Pinterest
    • Pinterest rebuilt their mobile site as a PWA and core engagements increase by 60%. They also saw a 44% increase in user-generated ad revenue and time spent on the site has increased by 40%.
  • Flipkart
    • Flipkart’s PWA is driving 50% of its new customer acquisition. Nearly 60% of visitors to the PWA had previously uninstalled the native app primarily to save space.
  • OLX
    • OLX experienced 250% more re-engagement using push notifications and 146% higher click-through rate on ads. The PWA takes 23% less time to interactive resulting in 80% lower bounce rates.
  • Infobae
    • Infobae’s PWA beta has 230% longer session and 3× more page views than the previous mobile site.
  • Selio
    • Selio’s average customer acquisition cost for Progressive Web Apps is 10× less than for native apps.
  • Google
    • Google found that Progressive Web App install banners convert 5-6× more often than native install banners. More than half of users who chose to install a native app from these banners fail to complete installing the app whereas PWA installation is near-instant.
The combination of cheaper user acquisition costs, improved conversions and engagement metrics is a no-brainer. Even more if the user experience is guaranteed to be on par with native apps.

What is holding people back from PWAs?

Conventional wisdom is a trap

While talking to clients, I hear quite often “market leaders have native apps and it’s working for them, so why not us?”. Don’t get me wrong, native apps are great, but it’s not just the app, it’s the intrinsic cost of acquiring and engaging users, and building a real business on top of the app. For an app “to be working”, all sides of the equation need to be working.

There are also some structural challenges when it comes to learning that a native app may not be working.

First, it’s really rare to see true A/B comparisons: funding both PWA and native app development and comparing acquisition and engagement between them.

Second, it’s very common to see organizations that have separate teams for native and web endeavours, maybe even funded from different sources (marketing, R&D, etc) or even outsourced. This siloing often leads to long learning cycles, and with scarce information and communication is easy to miss the big picture. You may be growing your native app but not actually growing the business. Having a clear overview of long-term vs short-term metric growth and what leverages each platform (web, native, pwa) is key. Take into consideration that different platforms may be ruled by different economics (for example, native apps are vastly more expensive to distribute than web).

Timing

Add to Home Screen, Push Notifications and Offline support were not possible two years ago. Until Progressive Web Apps arrived, it wasn’t possible to engage users who wanted more of a service in all the ways that native apps could. The lack of push notifications and the presence on the homescreen stunted engagement. Also, the lack of meaningful offline behavior meant it was natural for services and users to choose the native app route once they decided a service was worthwhile.

Bad experiences and Misleading numbers

A typical technology path many organizations followed was first pretend their desktop website was fine because users would eventually pinch/zoom accordingly. Then “responsive” become a thing and everybody jumped over without slimming down JS, ads, images, etc.

For the reasons mentioned above besides the timing issues we mentioned earlier, the “responsive” endeavour was doomed from the get go. With poor results from responsive web apps, experimenting with native apps was the logical next step.

At first, early engagement numbers from native apps tend to be strong compared to “responsive web” sites. This follows from the historical feature and performance gap but also from a more subtle effect: users who are willing to download and install a native app, are likely already heavily engaged with the service.

Unfortunately, many will eventually hit the wall in terms of cost/benefit to native app distribution. It’s blindingly expensive to drive native app installs if you aren’t #1 in your market. It’s just hard to learn the true cost/benefit of native app strategies.

When making the decision, strive for the big picture and realise that your business goes beyond the app you building.

Embracing Progressive Web Apps with Ionic

Enough talking about the business side, let’s dive in and see how Ionic Framework is the ideal tech to build our Progressive Web App.

As we mentioned above, for a web app to be considered a PWA, it needs to comply with the following principles. Let’s see how Ionic Framework addresses each of them.

PWA Principle How Ionic handles it
Progressive - Works for every user, regardless of browser choice because it's built with progressive enhancement as a core tenet. Ionic uses many cutting edge web standards and APIs. Despite the fact that some of those don’t have full support across browsers, Ionic still works. In that sense, Ionic is considered to be progressive.
Responsive - Fits any form factor: desktop, mobile, tablet, or whatever is next. Ionic UI components are known for its flexibility. You can easily build a responsive UI with Ionic.
Connectivity independent - Enhanced with service workers to work offline or on low-quality networks. Ionic 4 apps can be easily combined with service workers to make apps work offline.
App-like - Feels like an app to the user with app-style interactions and navigation because it's built on the app shell model. Ionic framework is mobile first, all of Ionic components even adapt to the different platforms (ios, material design).
Fresh - Always up-to-date thanks to the service worker update process. Using different caching strategies inside our service workers we can control the freshness of our cached resources.
Safe - Served via HTTPS to prevent snooping and to ensure content hasn't been tampered with. We can achieve safety for our content by using a hosting provider that has HTTPS support.
Discoverable - Is identifiable as an "application" thanks to W3C manifest and service worker registration scope, allowing search engines to find it. The changes in how the router works in Ionic 4 made discoverability for our apps easy to achieve.
Re-engageable - Makes re-engagement easy through features like push notifications. Ionic 4 plays really nice with other libraries and packages that enable us to setup push notifications in a breeze.
Installable - Allows users to "keep" apps they find most useful on their home screen without the hassle of an app store. Ionic makes easy to achieve all the principles that enable our app to be installed (web app manifest, HTTPS, registered service worker).
Linkable - Easily share via URL, does not require complex installation. With the new Ionic 4 router, we don’t have to rely on deep-links anymore to link to the different parts of our web app.

For more information, please visit this detailed checklist.

Get your PWA up and running with Ionic

When it comes to the implementation, the new Ionic 4 presents two ways of building apps.

In an effort to attract new developers and become framework agnostic while embracing web components standard, Ionic 4 can be used out of the box without any companion framework. The @ionic/core package contains the Web Components that make up the reusable UI building blocks of Ionic Framework. These components are designed to be used in traditional frontend view libraries/frameworks (such as Stencil, React, Angular, or Vue), or on their own through traditional JavaScript in the browser.

On the other hand, honoring the well known Angular relationship with Ionic from the early days of the framework, Ionic 4 has an option to enhance the development experience and use Ionic in combination with the Angular capabilities you already know and love. The @ionic/angular package comes with Angular specific building blocks on top of @ionic/core components.

When it comes to building a Progressive Web App with Ionic, we can choose either way, but we have to take into consideration some details as we will need extra help to handle some details of the implementation (service workers and web manifest).

The new features in modern browsers that allow PWAs to work are web manifest files and service workers.

The web manifest is a simple JSON file that defines the fundamental parameters of the PWA, icons, app name, colors, screen orientation, etc.

Service workers, are the real key to the enhanced experiences that a PWA can offer. Acting essentially as a proxy between the user and the network, they are little javascript helpers that do the cool things that allow PWAs to work, such as caching data (and deciding when and how to use the cached info - for example to overcome a bad network connection), event triggers, taking care of push notifications, organizing updates and so on.

Framework agnostic PWA

Ionic has a PWA Toolkit that has everything you need to build progressive web apps without the dependency on a frontend framework such as Angular, React or Vue.

However under the hood it uses Stencil for compiling and building the app, Workbox to enforce best practices and easing the boilerplate needed when working with service workers and cache strategies (both crucial to build PWA’s), and Ionic Core for routing and all the reusable UI components Ionic is known for.

To be honest I haven’t looked in detail this approach. Although it has a solid foundation and looks promising, with new libraries or frameworks I tend to wait a little bit until they get more mature and stable. Besides that, I really like building Angular apps, so I might be a little bit biased.

Enhancing your PWA with Angular

If we choose this path, besides Ionic and Angular (@ionic/angular package) we will also need the @angular/pwa package to setup and ease the configuration of the service worker and web manifest in our project.

For more information, follow this link on adding service workers to your Angular app.

I have to admit that I feel more comfortable with this approach as Angular provides a solid, future proof framework to build apps. On top of that, adding Ionic with all the cool features it comes ends up in a winner combination.

In conclusion, the framework agnostic approach using the Ionic PWA Toolkit (that comes with Stencil, Workbox and Ionic Core) is really just a starting point for building an app. While following the Angular enhancement approach (which includes the @angular/pwa package) is ideal to add PWA features to an already existing @ionic/angular app.

Note: It’s worth mentioning that you can’t combine the PWA Toolkit with the @ionic/angular package. They use a different set of underlying libraries and are not intended to be used together. You either go with the @ionic/angular + @angular/pwa approach or with the PWA Toolkit (@ionic/core + Stencil + Workbox) approach.

Ionic is a great choice to build a PWA

Embracing the flexibility Ionic provides, either way will get you cover to build a progressive web app.

As I mentioned above, most of the principles that constitute a PWA are already baked into Ionic (Responsive, App-like, Discoverable, Linkable).

The others (Connectivity independent, Fresh, Re-engageable, Installable) relate to service workers and web manifest specification. These are handled both by Workbox or @angular/pwa.

The Progressive principle is intrinsic and refers to the ability to adapt to the features list available in the platform the app is running. For example if you run a PWA in Chrome on iOS, service workers are not available but that doesn’t prevent the PWA from working.

The remaining Safe PWA principle rely on your hosting provider respectively.

Today most browsers do support service workers and the use of HTTPS is well spread.

Probably, the not so well known, and thus more difficult to grasp, are the principles related to service workers and web manifest. Luckily both Workbox and @angular/pwa packages can ease the process of implementing and configuring some of their most hidden details. If you want to learn more about this, follow this awesome guide on service workers configuration using the @angular/pwa package.

Things that need to be polished

Although Ionic has all the PWA principles covered, if you want to go the extra mile regarding user experience and perceived performance you may find some blocks on the road.

There are two issues that I stumbled upon when playing around with @ionic/angular.

One of the issues is regarding server side rendering using Angular Universal in an @ionic/angular app.

And the other issue is about having lazy loadable routes working with the <ion-router-outlet> which at its core uses the Angular <router-outlet>. This issue only happens when you try to lazy load modules under named outlets (for example if you have an app with tabs navigation).

Both issues (server side rendering issue, lazy loading issue) are being handled by the Ionic team and hopefully they get fixed while Ionic 4 becomes more stable towards the release candidate.

Let’s build a Progressive Web App with Ionic 4

For this example app I will focus on showing you how easy is to go from 0 to 100 in terms of Progressive Web App principles checklist using Ionic Framework.

After we achieve that we will be adding more complex functionalities like push notifications and finally adjusting a little bit the styles to make the ionic app look great.

Adding PWA Capabilities - From 0% to 100%

Let’s start by creating a new Ionic app

$ ionic start pwaTalk sidemenu --type=angular

Note: In the setup process, I opted-out from Cordova and Ionic Pro SDK integration because in this ionic tutorial we are just focusing on the PWA nature of Ionic.

Let’s be accountable and test how a blank Ionic app scores in our PWA checklist.

To perform this audits we are gonna use Google suggested tool, Lighthouse. In particular we are gonna install and use the Lighthouse command line utility.

npm install -g lighthouse

It’s really simple to use, just run lighthouse URL-TO-TEST --view

Note that we run Lighthouse with the `--view` parameter to immediately open the HTML report in your browser.

#1 Run: Ionic blank app in a local dev server

Start the development server by running ionic serve (this will serve our app in localhost on port 8100) and then perform the audits with Lighthouse by running:

lighthouse http://localhost:8100 --view

Ionic PWA Lighthouse

The initial audit has bad results (19/100) due to the fact that we are serving the app from a development local server and also because the code is not built using performance enhancements (minification, etc).

#2 Run: Ionic blank app in a local production server

This time we will build our app with performance in mind. By running ionic build --prod we will be executing the build process with performance enhancements, and will get the outputs on our /www folder.

Besides a production build, we will also run our app with a more suitable web server (to use instead of the development server that comes with the Ionic CLI). For this sake we are gonna use the http-server package. This package enables you to create a local web server to serve the contents of any directory on your computer.

npm install -g http-server

Using the http-server utility is realy easy, just run http-server FOLDER-PATH -p PORT

Start the http-server by running http-server ./www -p 8888 (this will serve our app in localhost on port 8888) and then perform the audits with Lighthouse by running:

lighthouse http://localhost:8888 --view

Build a progressive web app with Ionic Framework

Although we improved from 19/100 to 46/100, there is still progress to be made. We haven’t even talked about any of the principles that constitute a PWA. We will cover that right away.

#3 Run: Ionic blank app in a local production server with @angular/pwa

As we mentioned before, the two main requirements of a PWA are a Service Worker and a Web Manifest. While it's possible to add both of these to an app manually, I strongly suggest using the @angular/pwa package to automatically add a service worker and an app manifest to the app. To add this package to the app, simply run:

ng add @angular/pwa

It’s time to see how the Ionic application performs now that it has PWA capabilities. Build the app again (to include the new PWA features) ionic build --prod start the http-server by running http-server ./www -p 8888 and then perform the audits with Lighthouse by running: lighthouse http://localhost:8888 --view

Ionic PWA

Look how we drastically improve the progressive web app score from 46/100 to 92/100. We didn’t achieve 100/100 because we are serving the project from our local server (localhost) and it doesn’t have HTTPS enabled. If you remember what we mentioned above, having a safe connection is one of the key principles that constitute a PWA.

This is the current status of our Ionic Framework App in terms of PWA completeness:

Progressive
Responsive
Connectivity independent
App-like
Fresh
Safe Missing because we are serving the app from a local server without HTTPS enabled
Discoverable
Re-engageable - Makes re-engagement easy through features like push notifications. Capable, not fully implemented.
Installable
Linkable

#4 Run: Ionic blank app with @angular/pwa deployed to Firebase Hosting

Final sprint, let’s add HTTPS support to achieve 100/100!

There are many hosting providers that offer HTTPS support, among them I find the Firebase Hosting product super easy to work with besides it’s free and provides many benefits for Progressive Web Apps, including fast response times thanks to CDN's, HTTPS enabled by default, and support for HTTP2 push. Follow me while I show you how to deploy your Ionic PWA to Firebase.

If you want to learn more about using Firebase with Ionic Apps, check our series of posts covering Authentication with Firebase, Ionic CRUD with Firebase, Firebase Storage, Firebase Database.

Let’s start by installing the Firebase CLI:

$ npm install -g firebase-tools

With the Firebase CLI installed, run firebase init from within our project’s folder. This will generate a firebase.json config file for you to adjust the deployment details.

Lastly, make sure caching headers are being set correctly. Ensure your firebase.json file looks like this:

{
  "hosting": {
    "public": "www",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "headers": [
      {
        "source": "/build/app/**",
        "headers": [
          {
            "key": "Cache-Control",
            "value": "public, max-age=31536000"
          }
        ]
      },
      {
        "source": "sw.js",
        "headers": [
          {
            "key": "Cache-Control",
            "value": "no-cache"
          }
        ]
      }
    ]
  }
}

That’s it! Simply deploy the app by running firebase deploy and once the app is deployed, perform the audits with Lighthouse by running:

$ lighthouse https://pwa-talk-meetup.firebaseapp.com --view

ionic framework pwa

Congratulations! We built a progressive web app with Ionic Framework with all the principles covered.

Although we achieved 100/100 in the Progressive Web Apps checklist, we need to go a step further to complete the implementation of the Push Notifications feature that constitutes the Re-Engageable principle.

In theory, all the mechanisms to make push notifications work in our PWA are already baked inside the Angular Service Worker that comes with @angular/pwa.

But push notifications require much more than just asking users for permissions to send notifications, we also need to setup and configure a push server that will handle the delivery of the notifications to the users in their associated devices.

Adding Push Notifications to our Ionic PWA

As I mentioned before, push notifications are one of the most important techniques to make our product or service more re-engageable.

Push Notifications are something normal in native mobile application such as iOS and Android apps, when the application is closed users still received the notifications. Good news, we can achieve the same experience with Progressive Web Apps!

In this ionic progressive web app tutorial we will go the extra mile and explain how to add push notifications to the @ionic/angular app we created earlier. For this purpose we are going to use Firebase Cloud Messaging as a push server to handle the delivery of notifications across platforms and devices.

If we wanted to implement it ourselves without using Firebase Cloud Messaging (FCM), we would need to somehow figure out how to find the device, connect to it and send data. FCM can do all this work for us. We can tell what’s the message and who to deliver it to and it will take care of the delivery. In my opinion it’s an incredible tool that’s completely free and really easy to set up.

The other piece that completes the push notifications implementation is an application server that will tell FCM what notification and to whom should be delivered. There are many ways you can build that.

If you already have a backend API, then you can easily integrate Firebase SDK into your tech stack and problem solved.

Otherwise, if you decided to go serverless (not using a centralized server), you can use a function-as-a-service offering like Firebase Cloud Functions that will let you run a piece of JavaScript code in the cloud, without having to care about where and how it’s executed.

For simplicity we won’t cover this in this progressive web app tutorial with Ionic Framework, we will just test everything is working by hitting Firebase Cloud Messaging directly using cURL.

Adding Firebase to an Angular project

We have lots of tutorials about Firebase and Ionic, but specially I recommend you to check Building a Ionic Firebase App step by step to see how to add many Firebase features into your Ionic Framework app.

Although we are building an Ionic app, we are relying on the Angular framework to build these functionalities.

This is a strong point to Angular, it has many official libraries and packages that make easy to add new functionalities like:

  • Server Side Rendering (@angular/universal)
  • Progressive Web Apps capabilities (@angular/pwa)
  • Service Workers (@angular/service-worker)
  • Material Design (@angular/material)
  • Firebase (@angular/fire)

The official @angular/fire library has many modules to help us interact with the different Firebase features, and we have other tutorials explaining how to use them inside an Ionic App:

  • Database(s)
    • Cloud Firestore - AngularFirestore
    • Realtime Database - AngularFireDatabase
  • Authentication - AngularFireAuth
  • Cloud Storage - AngularFireStorage
  • Push Notifications - AngularFireMessaging
  • Cloud Functions - AngularFireFunction

First of all, we will need to create a Firebase project. We have already done this when we deployed our sample app to firebase.

Proceed to install the dependencies:

$ npm install firebase @angular/fire --save

Next we need to setup the firebase configuration in our Angular environment files.

export const environment = {
  production: false,
  firebase: {
    apiKey: 'YOUR_API_KEY',
    authDomain: 'YOUR_AUTH_DOMAIN',
    databaseURL: 'YOUR_DATABASE_URL',
    projectId: 'YOUR_PROJECT_ID',
    storageBucket: 'YOUR_STORAGE_BUCKET',
    messagingSenderId: 'YOUR_SENDER_ID'
  }
};

You can find your configuration in the Firebase Console by opening Authentication > Web Setup

Build a PWA with Ionic 4 and Firebase

Finish the setup by importing the corresponding AngularFire modules in your app.module.ts file:

import { AngularFireModule } from '@angular/fire';
import { AngularFireMessagingModule } from '@angular/fire/messaging';

...

imports: [
    BrowserModule,
    AngularFireModule.initializeApp(environment.firebase),
    AngularFireMessagingModule
  ],

...

Setting up the Firebase Cloud Messaging Service Worker

Push Notifications only make sense if you are able to receive them even if the application is not in the foreground. This is possible to achieve in modern web applications thanks to service workers.

A service worker is a piece of JavaScript code that is able to run in the background, independently of the website which loaded it.

As I mentioned before, service workers are used mostly for two things:

  • Providing caching and offline access
  • Push Notifications

In our case, we are using @angular/service-worker that comes with @angular/pwa to handle caching and offline stuff in our Ionic PWA.

Although the @angular/service-worker has utilities to handle push notifications, we will use @angular/fire push utilities instead as they are specifically build to work with Firebase Cloud Messaging.

Houston we have a problem

So, the thing is, you can only register one service worker. And we are using different service workers both for caching/offline support, and push notifications. Worsening the situation, the official AngularFire documentation warns about possible incompatibilities between AngularFireMessaging and the Angular Service Worker.

Maybe I’m not completely understanding the technical incompatibilities between them, but I managed to get things working with a tiny workaround.

As you may know, the Angular Service Worker gets auto-generated on build time and outputs the ngsw-worker.js in your /dist folder.

On the other hand, following Angular Fire documentation, we created a service worker (firebase-messaging-sw.js) that will just hang out in the background (even after the ionic app has been closed by the user) waiting to detect new messages to notify the user.

importScripts('https://www.gstatic.com/firebasejs/5.4.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/5.4.1/firebase-messaging.js');

firebase.initializeApp({
  'messagingSenderId': ‘YOUR_SENDER_ID’
});

const messaging = firebase.messaging();

You can find your project specific sender-id under your Firebase project Cloud Messaging Settings.

To solve the restriction that forces us to install just one worker per application, we created a simple worker that combines the previous two (combined-sw.js).

importScripts('ngsw-worker.js');
importScripts('firebase-messaging-sw.js');

Finally, update your app.module.ts and register that combined worker instead:

ServiceWorkerModule.register('combined-sw.js', { enabled: environment.production })

Keep in mind that you will also need to add the two new service workers we manually added to the project inside the production build section of your angular.json file

"assets": [
  ...
  "src/combined-sw.js",
  "src/firebase-messaging-sw.js"
]

This will ensure those files get copied to the output folder when building your project.

Adding required Push Notifications configuration to the Web Manifest

You will also need to add extra configuration in your web app manifest specifying the gcm_sender_id which is a hard-coded value that indicates that FCM is authorized to send messages to this app. Make sure to add the browser sender ID in your manifest.json file exactly as shown (do not change the value).

"gcm_sender_id": "103953800507"

Note: Please don't confuse the "browser sender ID" with the “project-specific sender ID” value shown in your Firebase project settings. The browser sender ID for the manifest.json is a fixed value, common among all FCM JavaScript clients.

The project specific sender-id is the one we used in the previous step inside the firebase-messaging-sw.js file to initialize the firebase app.

Configure “VAPID” keys with FCM

Wait, what is VAPID?

VAPID stands for Voluntary Application Server Identification for Web Push protocol, and is a way to let publishers (like FCM to optionally identify themselves. A VAPID key is a cryptographic public/private key pair that is used in the following way:

  • The public key is used as a unique server identifier for subscribing the user to notifications sent by that server
  • The private key needs to be kept secret (unlike the public key) and its used by the application server to sign messages, before sending them to the Push Service for delivery

To subscribe your Ionic framework app to push notifications, you need to associate a pair of keys with your Firebase project. To do so, open the Cloud Messaging tab of the Firebase console Settings page and scroll to the Web configuration section. In the Web Push certificates tab, click Generate Key Pair.

Finally, the Firebase console displays a notice that the key pair was generated, and displays the public key string and date added.

Ionic PWA with Push notifications

Requesting users permission to send them notifications

Now that we have the Firebase Messaging Service Worker setup and installed, it’s time to ask the user if he wants to receive notifications from our App. By default, the browser will popup a UI for you, but it's highly recommend to ask the user for permission with a custom UI and only ask when it makes sense. If you blindly ask for permissions you have an extremely high chance of being rejected.

This is why we are not going to request push notifications permissions immediately after our Ionic PWA loads. We will add a button to trigger the permissions request.

home.page.html

<button (click)="requestPushNotificationsPermission()">
  Enable notifications!
</button>

We will use the AngularFireMessaging service to request user permission.

home.page.ts

import { Component } from '@angular/core';
import { AngularFireMessaging } from '@angular/fire/messaging';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage {

  constructor(private afMessaging: AngularFireMessaging) { }

  requestPushNotificationsPermission() {
    this.afMessaging.requestToken
      .subscribe(
        (token) => {
          console.log('Permission granted! Save to the server!', token);
        },
        (error) => {
          console.error(error);
        }
      );
  }
}

Notice that the AngularFireMessaging service requestToken function combines requesting permission and getting tokens. We need to get a token for each user in order to send them notifications.

Sending push notifications from our Ionic PWA

As we mentioned earlier, there are many ways you can send notifications to users from an Ionic progressive web app.

For simplicity, we will just test everything is working by hitting Firebase Cloud Messaging directly using cURL.

Go to your terminal console and run:

$ curl -X POST \
  https://fcm.googleapis.com/fcm/send \
  -H 'Authorization: key=YOUR-SERVER-KEY' \
  -H 'Content-Type: application/json' \
  -d '{
 "notification": {
  "title": "Hello World",
  "body": "This is Message from Admin"
 },
 "to" : "USER-REQUESTED-TOKEN"
}'

You can find YOUR-SERVER-KEY under your Firebase project Cloud Messaging Settings (explained in step 2).

Full Ionic Progressive Web App with Ionic 4

Known Issues

Angular app Service Workers issues on browsers based on Chromium < 60

While testing this ionic example pwa on Chrome browser v58 in Android I got issues with repeated visits to the site. After browsing for a solution, I found that it was a @angular/service-worker bug (issue 1, issue 2).

Luckily after upgrading Chrome on Android everything started working OK.

Notifications not working if permissions are granted inside the PWA

If the user grants permission to push notifications within Chrome browser in Android, then the notifications work ok. But if the user grants permissions inside the installed PWA, then the notifications don’t arrive.

Improving the User Interface

We won’t be adding much details to this Ionic PWA example, just some minor UI tweaks and some user interaction improvements related to the progressive web app install banner.

App logo and miscellaneous data

By default, the @angular/pwa package creates a manifest.json file with the Angular logo as the app icon. Be sure to update the manifest to use the correct app name and also replace the icons with your own.

PWA Install Banner

Just like we did with the push notifications permissions prompt, it’s highly recommended to show the app install banner to the user when it really makes sense.

By default, the browser (if it has support for service workers) will prompt the user to install the app as soon as the user starts interacting with the page.

Ionic PWA install banner
progressive web app install banner
add pwa to homescreeen

To achieve this, we need to prevent the event that the browser fires and save a reference to that event for later:

window.addEventListener('beforeinstallprompt', (e) => {
  console.log('beforeinstallprompt Event fired');
  // Prevent Chrome 67 and earlier from automatically showing the prompt
  e.preventDefault();
  // Stash the event so it can be triggered later.
  this.deferredPrompt = e;
});

Once we have the reference to the event it's easy to trigger the install prompt at any time:

showInstallBanner() {
  if (this.deferredPrompt !== undefined && this.deferredPrompt !== null) {
    // Show the prompt
    this.deferredPrompt.prompt();
    // Wait for the user to respond to the prompt
    this.deferredPrompt.userChoice
    .then((choiceResult) => {
      if (choiceResult.outcome === 'accepted') {
        console.log('User accepted the A2HS prompt');
      } else {
        console.log('User dismissed the A2HS prompt');
      }
      // We no longer need the prompt.  Clear it up.
      this.deferredPrompt = null;
    });
  }
}

Finally, let's add a simple “Install the app” button and bind it to that method.

More meaningful app pages

Let’s make our Ionic PWA more appealing than the Ionic starter by adding some pages to showcase the ten principles of Progressive Web Apps mentioned earlier.

progressive web apps in ionic
progressive web app example
Ionic PWA example app

Room for improvements

Although we achieved a full featured progressive web app, there are plenty of details we can work on. In this detailed checklist you can find advanced checks to enhance the performance and usability of your PWA and take it from a baseline to exemplary experience.

Two of the most important things that you should consider to improve the app is adding both server side rendering and lazy loading capabilities. These will help you achieve better user perceived performance as your app will have faster interaction times.

The State of PWA Today

Most browsers fully support the underlying technologies that enable progressive web apps, and there are others like Safari for iOS and macOS that have been silently adding basic support for Progressive Web Apps. Check this in-depth post to learn what you can and can’t do currently in terms of PWAs in iOS.

Capabilities of PWAs on iOS

With the Web Platform on iOS you can access:

  • Geolocation
  • Sensors (Magnetometer, Accelerometer, Gyroscope)
  • Camera
  • Audio output
  • Speech Synthesis (with headsets connected only)
  • Apple Pay
  • WebAssembly, WebRTC, WebGL as well as many other experimental features under a flag.

What PWAs can do on Android and not on iOS

  • On Android you can store more than 50 Mb
  • Android doesn’t delete the files if you don’t use the app, but it can delete the files under storage pressure. Also, if installed or used a lot by the user the PWA can request Persistent Storage
  • Bluetooth access for BLE devices
  • Web Share for accessing native share dialog
  • Speech Recognition
  • Background Sync and Web Push Notifications
  • Web App Banner to invite the user to install the app
  • You can customize (a little bit) the splash screen and the orientations you want
  • With WebAPK and Chrome, users can’t install more than one instance of a PWA
  • With WebAPK and Chrome, the PWAs appears under Settings and you can see data usage; on iOS everything appears under Safari
  • With WebAPK and Chrome, the PWA manages intents for its URL, so if you get a link to the PWA, it will be opened in standalone mode and not within the browser’s window.

Final thoughts about PWAs in Ionic Framework

I really hope you enjoyed this post about Progressive Web Apps with Ionic Framework and Firebase. It was really a pleasure to share my knowledge with you, I hope you feel the same and please let me know your feedback in the comments below.

As I mentioned before, I do believe PWAs are the future (or should I say the present?). Stay tuned as I will be updating this post as new features become available and more Ionic 4 tutorials so subscribe to our newsletter to keep learning Ionic Framework!

See you in the next ionic tutorial.