A lot of you would have heard of Progressive Web Apps (PWA) and the benefits for building this type of user experience that has been coined and promoted by Google. Without going into too much detail about why you should upgrade your standard web app into a progressive web application, which is covered in the above documentation from Google, in a nutshell a PWA means your web application is
- Reliable: Even in flaky networks, your website will load instantly
- Fast: Website responds instantaneously with silky smooth animations and no janky scrolling
- Engaging: Feels like a natural app, which you can launch from home screen and can receive push notification
Following the above, one key strategy to take on and consider when building a PWA is caching. And according to Google, there are no hard and fast requirements around what to cache. Following the terminology itself, it can be useful to think of our caching and offline strategy progressively, following a series of milestones. The first step we can take is to add a simple service worker and cache static assets, such as stylesheets and images, so these can be quickly loaded on repeat visits. Each milestone allows us to deploy separately for it, measure the performance gains with every step taken, and progressively roll out a better PWA.
Recently my team got the chance to build a proof of concept for one of our retail clients who have an Episerver Commerce website that they wanted to be upgraded to a progressive web application. In this PoC, we started by enabling offline viewing for the website, allowing the online shoppers to navigate to the site with seamless experience regardless of network conditions even those without Internet at all. Unfortunately, this Episerver Commerce site is rendered from the server, which means we can only cache the pages the customers would have visited, as opposed to Single Page App (SPA) where you typically can cache all page templates as soon as customers hit the site for the first time. In this post, I'd like to share the first steps we've taken to make a PWA out of this existing website.
Below are the offline cache strategies we have applied:
- Network First (Network Falling Back to Cache) - This strategy is applied on
- All server-rendering pages including product listing page, product details page, cart page, etc
- All API's consumed for retrieving data to ensure responses are retrieved as quickly as possible. Cached responses will then subsequently be returned, falling back to a network request if not cached. As expected, the network request will the updated the cache.
- Network Only - This strategy is applied on the Checkout API as we don't want to apply any cache to the checkout process
- Stale-While-Revalidate - This strategy is applied on
- Global assets, Site resources and links
- 3rd party script and css references
For more details about the cache strategies, please refer to the following articles
Now, let's look at the implementation.
With the current frontend build based on Angular JS 1.x, where it's build relies on Node and Gulp toolkit, we started our implementation using the WorkBox module, a set of libraries and Node modules that makes it easy to cache assets and take full advantage of the features used to build Progressive Web Apps.
First, let's declare workbox module in the package.json file
Then in the gulpfile.js, we can simply define a task for generating the ServiceWorker "sw.js", like this
var gulp = require('gulp'),
Quick explanation on the couple of items mentioned in the above script:
- "swSrc" is the ServiceWorker definition where we define all the cache strategies
- "swDest" is the destination in which we'd like to generate the output ServiceWorker file to. And in our case is the root folder of CMS.
Below is what the source "sw.js" looks like
Next, you can simply run the "buildSw" task in Command Prompt
1. "_PWA_Manifest.cshtml" which will then be included into the <head> tag
<meta name="theme-color" content="#808285" />
and as you can see we will need to create some app icons declared using "apple-touch-icon" or a "manifest.json" file
"manifest.json" should look like this
2. "_PWA.cshtml" for the ServiceWorker which will then be placed right before the body closing tag </body>
Ta-da! We've now taken the first step into building a PWA out of an existing Episerver website. We've just enabled offline viewing for visited pages on the website. Please note this doesn't yet support offline checkouts and will be progressively (pun intended) improved to make a full-blown PWA out of this.