PWA Directory: Loading content faster in the Application Shell.

This article was co-authored by Julian Toledo.

When a user visits PWA Directory for the first time, a Service Worker is installed and the Application Shell is cached. On the following visits, the first render is accelerated by serving the cached shell from the Service Worker. Once loaded, the shell will issue a request for the page content and render it when the response arrives.

The upside of this approach is that the first render for the page happens much faster: on an Emerging Market 3G connection, the first render could take up to 3 seconds. With this approach, it takes about 750ms. Check the WebPageTest timeline here.

The downside is that the request for the content, which is most likely what the users came to the website for, will only start after the shell is loaded and the Javascript is executed, potentially making the full content slower to load than if it was entirely loaded from the server. Here’s a quick analysis of the timeline:

One possible optimisation to this flow is that, although the request for the page is replaced by the shell on the Service Worker, we still have the URL for the content. In PWA Directory, we can use this original URL to derive the URL for the content, for example, we are adding the contentOnly=true parameter to request the server to return html content without headers/footers already included in our shell.

Since we now know the URL for the content, we can start the request for it earlier, from the Service Worker, so when it’s requested again from the Application Shell, the browser is smart enough to understand that a request for the same resource has already been made and uses the same response for both docs.

Check the timeline for this approach here.

As shown in the graphic above, the requests starts much before the Javascript work on the Main Thread. saves the application about 300ms when fetching the content. One interesting characteristic is that those 300ms are saved even on a fast network, since the time to load the Javascript file is something that is CPU bound instead of network bound.

A small caveat for this solution is to make sure that the content has max-age, of at least a few seconds, to assure that the browser reuses the original page.html?contentOnly=true request and does not make the request again because it has expired.

The code that implements this is straightforward. Check how it works on this pull request at PWA Directory’s Github repository.