Thursday, 19 October, 2017 UTC


Summary

Progressive Web Apps are fast becoming a major deployment target. Recent releases like the the Starbucks PWA provide validation that progressive web apps have arrived. Because Ionic is built on the web, Ionic apps can work anywhere the web runs, including as a PWA. In today’s post, we will go over exactly what a PWA is and how to deploy your next Ionic app as a PWA!!
First, let’s briefly define what a PWA is. We’ll go with Google’s official definition on this one:
Progressive Web Apps are user experiences that have the reach of the web, and are:
  • Reliable – Load instantly and never show the downasaur, even in uncertain network conditions.
  • Fast – Respond quickly to user interactions with silky smooth animations and no janky scrolling.
  • Engaging – Feel like a native app on the device, with an immersive user experience.
This new level of quality allows Progressive Web Apps to earn a place on the user’s home screen.
Before we cover how to transform your Ionic app into a PWA, let’s answer some of the most common questions people have about PWAs:

Do PWAs only work on mobile? Or desktop?

Both, it’s just a web app, so it should look good anywhere the web runs! And with Ionic 3 and above, the grid system will work beautifully on any size screen.

Will PWAs kill native apps?

No, there are use-cases for both. For example, does a conference need an installable app? Or would they convert better if the users could get the same experience through a website? Probably the latter as you would not want to go through the process of installing an app just to use it for a limited time. PWAs are what you are looking for when you want to give users an instant experience as nothing is faster than just clicking on a link. Have a more in-depth experience that is possibly using features not yet found on the web? Then a native app is probably what you need. Ionic has your back no matter what platform you want to deploy to, all from one single codebase!

What is this Service Worker thing?

Service workers are scripts the browser runs in the background, separate from a web page, that allow us to implement features such as push notifications, background sync, dynamic caching of assets and more!
There’s support for a bunch of other stuff coming, in the mean time, you can check out:
  • What Web Can Do Today to see what behaviors are supported.
  • is Service Worker ready? to see the browser support.
A couple of things to note about Service Workers:
  • They are JavaScript Workers, so they cannot access the DOM directly. Instead, a service worker can communicate with the pages it controls by responding to messages sent via the postMessage interface, and those pages can manipulate the DOM if needed.
  • It is terminated when not in use and restarted when it is next needed, so you cannot rely on global state within a service worker’s onfetch and onmessage handlers. But, if there is information that you need to persist and reuse across restarts, service workers do have access to the IndexedDB API.
  • Service Workers make extensive use of promises, so if you are new to promises, I recommend checking out this excellent blog post.
  • They only run on HTTPS connections. During development you will be able to use service worker through localhost, but to deploy it on a site you will need to have HTTPS setup on your server. This is because using a service worker you can hijack connections, fabricate, and filter responses. Powerful stuff. So you might use that stuff to better your app, but a man-in-the-middle attack might not.

How do I create links? After all, it is a web app.

Ionic has an impressive deep-linking feature that works great with PWAs. Also, with the update to Ionic-angular 3, they created an IonicPage module which lets us add, among other things, a static (or dynamic) URL for pages.
This means that users can easily share that URL and anyone they share it too will be taken right to the page they were on!

PWA, here we come!

Transforming an Ionic Framework app into a PWA is not easy, it is hard work, but we are going to go through every step here. First, go into src/index.html and find the below commented out script that enables the service worker and uncomment it:
<script>
  if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('service-worker.js')
      .then(() => console.log('service worker installed'))
      .catch(err => console.log('Error', err));
  }
</script>
And that is it. You now have a PWA. Did you believe me when I said it was hard?
I am not kidding, that is all you need to do to go from web app to PWA. You can then deploy your app to a server and immediately access it from your browser. Now, remember to put on your new PWA champion badge!

Further Optimizations

Let’s do some other tweaks to remove unnecessary things. These steps aren’t necessary but are good to do if you are deploying your app only as a PWA.
Currently, right above that service worker script is the script to call cordova.js. If you are only going to run the app as a PWA and not a cordova app, go ahead and comment it out.
<!-- cordova.js required for cordova apps -->
<!--<script src="cordova.js"></script>-->
If your only deploying this as a PWA you can go inside app.component.ts, and remove the platform and plugin calls:
import { Component } from '@angular/core';
import { TabsPage } from '../pages/tabs/tabs';

@Component({
  templateUrl: 'app.html'
})
export class MyApp {
  rootPage: any = TabsPage;

  constructor() {}
}
You can also go into the app.module.ts file and remove the imports for the StatusBar and SplashScreen plugins.

Web Manifest and Service Worker

The web manifest and Service Worker are what officially make our app a PWA. Let’s take a look at these two features.
Let’s examine the web manifest and the service worker to see what’s going on. First, open src/manifest.json
{
  "name": "Ionic",
  "short_name": "Ionic",
  "start_url": "index.html",
  "display": "standalone",
  "icons": [{
    "src": "assets/imgs/logo.png",
    "sizes": "512x512",
    "type": "image/png"
  }],
  "background_color": "#4e8ef7",
  "theme_color": "#4e8ef7"
}
This is the standard web manifest that comes with the app. Let’s go through each option:
  • "name": "Ionic", => This is the name of our application.
  • "short_name": "Ionic", => This is our short name, used when there’s not enough space for the name. It is most commonly used when the user adds the application to the home screen.
  • "start_url": "index.html", => This is the URL the app is going to open to.
  • "display": "fullscreen", => Defines the developer’s preferred display mode for the web application. When using fullscreen all of the available display area is used, and no browser chrome is shown.
  • The icons object lets you set the icons your app will use depending on the resolution of the screen. The highest resolution icon (512×512) will also be shown on the splash screen of the application
"icons": [{
  "src": "assets/imgs/logo.png",
  "sizes": "512x512",
  "type": "image/png"
}]
  • "background_color": "#4e8ef7", => Defines the expected background color for the web application.
  • "theme_color": "#4e8ef7" => Defines the default theme color for an application. This will affect things such as the notification bar color on Android.
Make sure to add your preferred logo to src/assets/img/logo.png. This is the logo the PWA will display when the user adds it to the home screen, and it will show it on the splash screen when the user opens the app through the homescreen or app drawer in Android.
For a list of all the properties, you can check out this section of the MDN docs
Now let’s check out the src/service-worker.js file:
'use strict';

importScripts('./build/sw-toolbox.js');

self.toolbox.options.cache = {
  name: 'ionic-cache'
};

// pre-cache our key assets
self.toolbox.precache(
  [
    './build/main.js',
    './build/main.css',
    './build/polyfills.js',
    'index.html',
    'manifest.json'
  ]
);

// dynamically cache any other local assets
self.toolbox.router.any('/*', self.toolbox.cacheFirst);

// for any other requests go to the network, cache,
// and then only use that cached resource if your user goes offline
self.toolbox.router.default = self.toolbox.networkFirst;
This is the default service worker setup that Ionic uses. This setup will pre-cache all of your static assets ensuring that your app loads reliably and fast under any network condition.

Deploying

Now it is time to get everything ready for deploy, we want to minify, uglify, and other-fy words you can think of. Ionic will do all the hard work for us, we just need to open up the terminal and run:
npm run ionic:build -- --prod
That command will activate Angular’s production mode, and run a full production build so you can get the smallest bundle possible.
It will take a while, especially the first time you run it, but it is worth it. Once it is finished you can upload your www directory to whichever hosting service you prefer.
Just like that, we took our existing Ionic app and made it into a PWA! Because Ionic is built completely using web technologies, we can deploy our app to cordova and as a PWA using the same codebase. Also, we are working on making this process even better, including completely automating our service worker setup using the CLI. The future is awesome!