Codementor Events

Vue PWA Plugin

Published Mar 18, 2019

Ever wondered how you can create a PWA with Vue? It's actually pretty easy 😃. In this blog post I’ll show you how you can precache your files and how you can apply the difference cache strategies.

Initialize PWA Plugin

To get going you need at least version 3 of the Vue CLI. After that you have to run this command:

vue add @vue/pwa

Once you’ve executed it you’ll see a couple of files that weren’t there before. The first one is the registerServiceWorker.js. This file will register your service worker within the browser. If you look into the code you’ll see that you shouldn’t use service workers for local development. The reason for that is that caching files while developing locally might result in unexpected behavior. Especially if you precache some of your development files.

Furthermore you shouldn’t try to make it run locally, i.e. changing the if case condition in the registerServiceWorker.js to ‘development’. The service worker is not designed to handle local environment — changing your base url within the vue.config.js will break the loading of a service worker for local development anyway.

Since the other files don’t matter for now we will look into the configuration of precaches.

Configuring the precaches

Once you’ve build your project via npm build you’ll see a service-worker.js file within your dist directory. The content should be:

...

importScripts("https://storage.googleapis.com/workbox-cdn/releases/3.6.3/workbox-sw.js");

importScripts(
  "/precache-manifest.415f21068aad841ef1d7c6250910c3ca.js"
);

workbox.core.setCacheNameDetails({prefix: "todoapp"});

/**
 * The workboxSW.precacheAndRoute() method efficiently caches and responds to
 * requests for URLs in the manifest.
 * See https://goo.gl/S9QRab
 */
self.__precacheManifest = [].concat(self.__precacheManifest || []);
workbox.precaching.suppressWarnings();
workbox.precaching.precacheAndRoute(self.__precacheManifest, {});

As you might already see the service-worker does use a file called:
precache-manifest.415f21068aad841ef1d7c6250910c3ca.js

This file adds most of your assets to the precache. You can see this in effect if you run a local http-server. If you don’t have a local webserver you can run the following commands:

npm install http-server -g
http-server dist -p 8081 -a localhost

If you now open the network tab within your browser you’ll see that the js and css files will be loaded by the service worker.

1*yVlSjig7h8i6EhfDczrCNQ.png

But maybe you don’t want to cache files and only 1. The way you can do this is to configure the vue.config.js (located at the root of your project). If you add the lines

pwa: {
    workboxPluginMode: 'InjectManifest',
    workboxOptions: {
        swSrc: 'public/service-worker.js',
    }
}

you can create a custom service-worker.js file within your src directory. The ‘InjectManifest’ ensures that the precache-manifest.js will also be imported in your custom file. But for now we only what to load 1 file. Add this to your src/service-worker.js

workbox.precaching.precacheAndRoute([{
    "revision": "17ecfaee522eaf5b3ad9c9aa1b2973cc",
    "url": "/manifest.json"
}]);

and now build your project again. Now you might want to unregister your service worker within the application tab within your browsers(chrome) dev tools. Afterwards you refresh the page 2 times and you will see that the manifest will indeed be served by the service worker.

But since the most important files are already precached it might be more useful for you to exclude some files. To achieve this we will at first configure our service-worker.js so that precache-manifest.js will be loaded again. For this add:

self.__precacheManifest = [].concat(self.__precacheManifest || []);
workbox.precaching.suppressWarnings();
workbox.precaching.precacheAndRoute(self.__precacheManifest, {});

to your service-worker.js. Now open your vue.config.js and exclude the files you want:

...
workboxOptions: {
    swSrc: 'public/service-worker.js',
    exclude: /\.js$/
}
...

Afterwards you can open your precache-manifest.js within the dist directory and you’ll see that there are no js files anymore. For more options like include etc. see: workbox-options.

If you want to see what files got actually cached you can either look them up within the indexeddb (application tab in browser dev tools) or within the cache storage.

Configure API Caching

To create the request I’ll also use axios — but you can of course use any client you want. My call now looks like this:

axios.get("https://jsonplaceholder.typicode.com/todos/1")
    .then(e => console.log(e))
    .catch(e => console.log(e));

If you still have the exclude entry for your workbox it might be good to remove this for now. You also might want to use a guest window(user) every time you change something with the service-worker.js

One of the easiest ways to support caching is to use the caching strategies from workbox (if you want to know the difference between the strategies feel free to write me 😃). In our example we will use the cache first approach — which means that the cache will be evaluated first and only if the cache is empty the network will be used. To achieve this we’ll add these lines to our service-worker.js

workbox.routing.registerRoute('https://jsonplaceholder.typicode.com/todos/1', workbox.strategies.cacheFirst({
    cacheName: 'placeholder-cache',
}));

Whats happening here is that we say for the given route we want to use the cache first strategy with the cache placeholder-cache. If you now open your browser and refresh 2 times you’ll see this response:
image.png

Since Workbox provides really good messages you can see step by step whats happening and if you want to see the response that is used you can look for that within the application tab of your browsers dev tools. There you’ll find a cache with the given name.

But you may want to add your own logic if the network fails. For this you can evaluate the promise of the strategy like this:

const placeholderHandler = workbox.strategies.cacheFirst({
    cacheName: 'placeholder-cache',
});

workbox.routing.registerRoute('https://jsonplaceholder.typicode.com/todos/1', args => {
    return placeholderHandler.handle(args).then(response => {
        console.log("Online: Fetch was called successful");
        return response;
    }).catch(err => {
        console.log("no cache data");
    });
});

Here you have the possibility to change response values. This will be it for now.

If you have any questions feel free to write a comment or e-mail me 😃

Discover and read more posts from Mario
get started
post commentsBe the first to share your opinion
Gabriel Weibel
4 years ago

Hi from Switzerland. I am student and I will start my thesis in October 2020. I want to do a PWA. I have now spent about 2 days with googling. I am still unable to make a Vue PWA app with a .NET core backend. Backend communication in a pure Vue web app is not a problem for me, but as soon as it comes to caching the Api requests, I can’t get any further. We don’t want to start with a background sync (although I actually want to have that in there too). Can you help me or someone else?

Hesham El Masry
5 years ago

if you can manage to wrap this up on a github repo will be really helpful cause you are the only one on all the pages i searched on google for 3 hours who is doing it correctly and recent.

Show more replies