Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue Router History Mode with PWA in Offline Mode

To get history mode working with Vue-Router you need to return the contents of your main page when trying to access a route that doesn't exist. For example when you visit mypwa.com/route1 your server checks if there is a resource at route1 and if there isn't, it returns the contents that is found at mypwa.com/ (but without redirecting you). This is great and works when you're online, but it requires your server to do the actual re-routing.

If you have a PWA that's meant to work offline, you need this re-routing to work without the server being available.
The problem is this: visiting mypwa.com/ when you're offline works. After loading it you can then navigate to mypwa.com/route1 from inside the app. However, if you try to navigate directly to mypwa.com/route1 whilst offline you will get a 404 error because mypwa.com/route1 is not cached, only / is cached. I suppose this means that you need some kind of fallback clause in your service worker? Does anyone know of a way to achieve this? Is there a common way to do it with sw-precache-webpack-plugin?

like image 891
MattCochrane Avatar asked Apr 22 '18 08:04

MattCochrane


People also ask

What is History mode in vue router?

# HTML5 History Mode. The default mode for vue-router is hash mode - it uses the URL hash to simulate a full URL so that the page won't be reloaded when the URL changes. To get rid of the hash, we can use the router's history mode, which leverages the history.pushState API to achieve URL navigation without a page reload:

What is the default mode for vue router?

The default mode for vue-router is hash mode - it uses the URL hash to simulate a full URL so that the page won't be reloaded when the URL changes.

How to get rid of the hash of a vue router?

To get rid of the hash, we can use the router's history mode, which leverages the history.pushState API to achieve URL navigation without a page reload: const router = new VueRouter({ mode: 'history', routes: [...] })

Is it possible to build a progressive web app with vue router?

Today we will create a progressive web app (PWA) based on Vue.js with Vue Router, featuring code splitting with webpack. Luckily, building progressive web apps has never been easier.


2 Answers

You need to set the navigateFallback option in your vue.config.js file:

pwa: {
  workboxOptions: {
    navigateFallback: 'index.html'
  }
}

It will automatically add the necessary code to your service worker:

workbox.routing.registerNavigationRoute(workbox.precaching.getCacheKeyForURL("index.html"));

I had the same problem and I found the solution here: https://github.com/vuejs/vue-cli/issues/717#issuecomment-382079361

like image 146
clem Avatar answered Oct 27 '22 02:10

clem


If your site is a single page app, you can use a NavigationRoute to return a specific response for all navigation requests.

workbox.routing.registerNavigationRoute('/single-page-app.html')

In my case in vue :

workbox.routing.registerNavigationRoute('/index.html')

Whenever a user goes to your site in the browser, the request for the page will be a navigation request and will be served the cached page /single-page-app.html.

Note: You should have the page cached via workbox-precaching or through your own installation step).

By default, this will respond to all navigation requests, if you want to restrict it to respond to a subset of URL’s you can use the whitelist and blacklist options to restrict which pages will match this route.

Update: Workbox V5

const handler = workbox.precaching.createHandlerBoundToURL("/index.html");

const navigationRoute = new workbox.routing.NavigationRoute(handler);

workbox.routing.registerRoute(navigationRoute);
like image 38
HanJeaHwan Avatar answered Oct 27 '22 02:10

HanJeaHwan