Vue Js router in history mode

There are two options as of now that I can think of: using a service worker, or manually adding all your routes as files.

Option 1: using a service worker

Service workers are really cool. They run in the background, and can be used to do stuff like cache assets and modify network requests, without a server - it all happens in your browser. Service workers are also fully async and HTTPS only. The only problem with service workers is that you need to register them before they can be used - so a user will have to naviate to the home page of your site first in order to be able to navigate correctly to other pages.

Step 1: create your service worker file

You’ll need to create a js file, usually called sw.js, at the root of your site, with something like the following in it:

self.addEventListener("fetch", event => { // listens to requests on your project
  let modifiedUrl = /^https:\/\/projectname\.glitch\.me/.test(event.request.url) // is the url on the same domain?
    && !/\.(js|css|svg|png|jpg|vue|ico)/.test(event.request.url) // is it not a static asset that we don't want to render as a page?
    && !/vite/.test(event.request.url) // only needed if you're using vite, same purpose as above
    ? "/" : event.request.url; // if all of the above are true, return our index.html instead of glitch's usual 404 page
  event.respondWith(fetch(modifiedUrl)); // respond with the correct response
});

This will need to be adjusted for your needs - replace projectname with ypur project name, and in the section that goes (js|css| ... |ico), make sure to add any file extensions that your site may need to be served normally.

Step 2: register your service worker

Once step 1 is completed, if you go to your site it will act as it usually does i.e. not work. So, you’ll need to add the following code to the top of your main script file, assuming it has the defer tag or is loaded at the end of the <body> - otherwise, wrap this in a window.addEventListener("load", () => { ... });.

if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('/sw.js').then(function(registration) {
      // Registration was successful
      console.log('ServiceWorker registration successful with scope: ', registration.scope);
    }, function(err) {
      // registration failed :(
      console.log('ServiceWorker registration failed: ', err);
    });
  });
}

You can get rid of the console.logs if you’d like.
Now, naviagate to your home page, enter another url on your site in your browsers navigation bar, and you should see your site working correctly! And as long as all your users go to your home page first, it’ll work for them as well :smiley:

Option 2: manually add all your routes

This one’s really simple. For each of your routes, e.g. this/is/a/page, copy your index.html to this/is/a/page/index.html, and it should Just Work™. However, this will only work if your project is fully static and not a generated static site. If it is a generated static site, you’ll have to either write your own extra build script and/or vite/webpack/rollup/whatever plugin that imports your routes and copies build/index.html to build/this/is/a/page/index.html. If this is the case, I’ll leave you to your own devices to build that :slight_smile:

Obviously neither of those options are particularly desirable, but who knows, maybe official support for this will come one day :crossed_fingers:
Hopefully this very long post will help you, and happy glitching :slight_smile:

P.S. I’d recommend checking out Redirect non-existing routes to index.html for Generated Static Sites and giving it a vote :wink:

2 Likes