Getting Started with Progressive Web Apps

There's been much welcome discussion about Progressive Web Apps lately. They're still a relatively new model, but their principles can equally enhance apps built with vanilla JS, React, Polymer, Angular or any other framework. In this post, I'll summarize some options and reference apps for getting started with your own progressive web app today.

What is a Progressive Web App?

Progressive Web Apps use modern web capabilities to deliver an app-like user experience. They evolve from pages in browser tabs to immersive, top-level apps, maintaining the web's low friction at every moment.

It's important to remember that Progressive Web Apps work everywhere but are supercharged in modern browsers. Progressive enhancement is a backbone of the model.

Aaron Gustafson likened progressive enhancement to a peanut M&M. The peanut is your content, the chocolate coating is your presentation layer and your JavaScript is the hard candy shell. This layer can vary in color and the experience can vary depending on the capabilities of the browser using it.

Think of the candy shell as where many Progressive Web App features can live. They are experiences that combine the best of the web and the best of apps. They are useful to users from the very first visit in a browser tab, no install required.

As the user builds a relationship with these apps through repeat use, they make the candy shell even sweeter - loading very fast on slow network connections (thanks to service worker), sending relevant Push Notifications and having a first-class icon on the user's home screen that can load them as fullscreen app experiences. They can also take advantage of smart web app install banners.

Progressive Web Apps are:

Progressive - Work for every user, regardless of browser
choice because they’re built with progressive enhancement as a core
tenant.

Responsive - Fit any form factor, desktop, mobile, tablet, or
whatever is next.

Connectivity independent - Enhanced with service workers to
work offline or on low quality networks.

App-like - Use the app shell model to provide app-style
navigations and interactions.

Re-engageable - Make re-engagement easy through features like
push notifications.

Installable - Allow users to “keep” apps they find most useful
on their home screen without the hassle of an app store.

Linkable - Easily share via URL and not require complex
installation.

Progressive Web Apps also aren't unique to Chrome for Android. Below we can see the Pokedex Progressive Web App working in Firefox for Android (Beta) with early Add to home screen and service worker caching features running just fine.

One of the nice aspects of the "progressive" nature to this model is that features can be gradually unlocked as browser vendors ship better support for them. Progressive Web Apps such as Pokedex also of course work great in Opera on Android too with a few notable differences in implementation:

Principles

Web app manifest

The Manifest for Web applications is a simple JSON file that gives you, the developer, the ability to control how your app appears to the user in the areas that they would expect to see apps (for example the device home screen), direct what the user can launch and more importantly how they can launch it

The manifest enables your web app to have a more native-like presence on the user's home screen. It allows the app to be launched in full-screen mode (without a URL bar being present), provides control over the screen orientation and in recent versions of Chrome on Android supports defining a Splash Screen and theme color for the address bar. It is also used to define a set of icons by size and density used for the aforementioned Splash screen and home screen icon.

In my personal projects, I rely on realfavicongenerator to generate the correctly sized icons for both the web app manifest and for use across iOS, desktop and so on. The favicons Node module is also able to achieve a similar output as part of your build process.

Chromium-based browsers (Chrome, Opera etc.) support web app manifests today with Firefox actively developing support and Edge listing them as under consideration. WebKit/Safari have not yet posted public signals about their intents to implement the feature just yet.

Service worker for offline caching

A service worker is a script that runs in the background, separate from your web page. It responds to events, including network requests made from pages it serves. A service worker has an intentionally short lifetime.

It wakes up when it gets an event and runs only as long as it needs to process it. Service worker allows you to use the Cache API to cache resources and can be used to provide users with an offline experience.

Service workers are powerful for offline caching but they also offer significant performance wins in the form of instant loading for repeat visits to your site or web app. You can cache your application shell so it works offline and populate its content using JavaScript.

Our team also maintains a number of service worker helper utilities and build tools that we find useful for reducing the overhead in getting service worker setup. They're listed over on Service Worker Libraries. The two main ones are:

Chrome, Opera and Firefox have all implemented support for service worker with Edge having positive public signals about interest in the feature. Safari briefly mentioned interest in it via one engineer's proposed five year plan.

Push notifications for re-engagement

Push notifications allow your users to opt-in to timely updates from sites they love and allow you to effectively re-engage them with customized, engaging content.

Effectively, you can build web apps that users can engage with outside of a tab. The browser can be closed and they don't even need to be actively using your web app to engage with your experience. The feature requires both service worker and a web app manifest, building on some of the features summarized earlier.

The Push API is implemented in Chrome, in development in Firefox and under consideration in Edge. There are no public signals from Safari about their intent to implement this feature just yet.

Michael van Ouwerkerk from the Chrome team also has a 6 min intro to Push if you're more video inclined.

Layering in advanced features

Remember, your user experience can have different levels of sweetness depending on the browser being used to view your web app. You're in control of the hard candy shell.

Additional features coming to the web platform such as Background Syncronisation (for data sync with a server even when your web app is closed) and Web Bluetooth (for talking to Bluetooth devices from your web app) can also be layered into your Progressive Web App in this manner.

Framework-friendly

There's really nothing stopping you from applying any of the above principles to an existing application or framework you're building with. A few other principles worth keeping in mind while building your Progressive Web App are the RAIL user-centric performance model and FLIP based animations.

I'm hopeful that during 2016, we'll see an increasing number of boilerplates and seed projects organically baking in support for Progressive Web Apps as a first-class citizen. Until then, the barrier to adding these features to your own apps isn't very high and are IMHO, quite worth the effort.

Architecture

There are different levels of how "all-in" one goes on the Progressive Web App model, but one common approach taken is architecting them around an Application Shell. This is not a hard requirement, but does come with several benefits.

The Application Shell architecture encourages caching your application shell (the User Interface) so it works offline and populate its content using JavaScript. On repeat visits, this allows you to get meaningful pixels on the screen really fast without the network, even if your content eventually comes from there. This comes with significant performance gains.

Jeremy Keith recently commented that in this type of model perhaps server-side rendering should not be viewed as a fallback but client-side rendering should be looked at as an enhancement. This is fair feedback.

In the Application Shell model, server-side rendering should be used as much as possible and client-side progressive rendering should be used as an enhancement in the same way that we "enhance" the experience when service worker is supported. There are many ways this can ultimately be approached.

My recommendation is reading our write-up on the architecture and evaluating how similar principles could be best applied to your own application and stack.

Getting started boilerplates

Application shell

Given that it covers both client and server-side portions of the model and there's quite a lot going on there, it will take some time to familiarize yourself with the codebase. It's otherwise our most comprehensive Progressive Web App starting point right now. Docs will be our next focus for this project.

The current version of PSK is missing support for some of the more advanced performance patterns (e.g Application Shell model, async loading) you find in some Progressive Polymer web apps.

We aim to try baking these patterns into PSK in 2016, but early experiments around this can be found in the Polymer Zuperkulblog app by Rob Dodson and the excellent Polymer Perf Patterns talk by Eric Bidelman.

If you have a preference for working with vanilla JS/ES2015 and are unable to use Polymer, Web Starter Kit may prove useful as a reference point you can reuse or steal code snippets from.

Progressive Web Apps with and without frameworks

A number of open-source Progressive Web Apps have already been built by members of the community both with and without JS libraries and frameworks. If you're looking for inspiration, the below repos might prove useful as reference. They're also just pretty damn good apps.