How does SSR go with PWA

Amanuel Nega picture Amanuel Nega · May 30, 2018 · Viewed 7.9k times · Source

How can one do SSR (Server side rendering) with PWA (Progressive web app)?

From what I understand,

SSR

The SSR runtime will load the page and run the necessary scripts to load the data on to the page. Then returns the rendered html. This is important for web crawlers which will not run javascript and browsers with no-script. At least the first impression will be usable.

PWA

Among others, PWA requires having a shell, which will be cached and the data will come after it. This means, even if the user is offline, the shell will be loaded.

?

So, if we're pre rendering the data, how can one cache the shell separate from the data?

Answer

Everettss picture Everettss · Jul 9, 2018

If you want to only cache shell from prerendered SSR view with initial data you must provide two views:

  1. /view-url with data from SSR
  2. /view-url?shell with only shell version, without data (you can change logic from url-query to for example request header).

When user for the first time enter /view-url you send 1. version and cache in Service Worker /view-url?shell. When user come back to /view-url you send him /view-url?shell from Service Worker cache by doing something like this:

const CACHE_NAME = 'cache-token';
const staticUrlsToCache = ['/style.css', '/script.js', '/logo.png'];
const shellUrlsToCache = ['/view-url'];
const urlsToCache = [
    ...staticUrlsToCache,
    shellUrlsToCache.map(url => `${url}?shell`),
];

self.addEventListener('install', event => {
    event.waitUntil(
        caches.open(CACHE_NAME).then(cache => cache.addAll(urlsToCache))
    );
});

self.addEventListener('fetch', event => {
    let request = event.request;

    const shellUrl = shellUrlsToCache.find(url => request.url.endsWith(url));
    if (shellUrl) {
        // here is real magic!
        request = new Request(`${shellUrl}?shell`);
    }

    event.respondWith(
        caches.match(request).then(response => response || fetch(request))
    );
});

The key point here is that you change original request /view-url to /view-url?shell in Service Worker!

If you want to read more about this technique I wrote an article about this problem How to combine PWA and isomorphic rendering (SSR)?