loading...
Cover image for Publish your Quasar SPA on Github.io with History Mode
Quasar

Publish your Quasar SPA on Github.io with History Mode

hawkeye64 profile image Jeff Galbraith ・4 min read

Frustrated with Github.io, because you can't run your Quasar SPA in history mode? Well, now you can!

Introduction

This article is intended to help you get your SPA published on Github.io with history mode turned on. This isn't a straight up process, so I figured I'd write some instructions on how to do it, to help out others who might be running into problems with this process.

Vue-Router

Vue-Router has two modes; 1) hash and 2) history.

With hash mode, there is only a single web page and routing takes over to display your pages correctly. Any backend server will be set up to serve only the index file.

With history mode, the concept is similar. However, the server is expecting static pages and for it to be handling the routing. If you have control over your own server, you would write some rewrite rules so the index file will be loaded, and just the index file, for every page, so the vue-router can take over from there.

So, you might also be asking yourself...

If hash mode works fine on github.io, why would anyone want to use history mode?

For myself, I wanted to be able to use anchor links. So, given a url with a hash symbol in it, the proper page will load up and content will automatically scroll to the anchor link.

The Conumdrum with Github.io

At the time I was investigating this, github.io didn't allow you to write any sort of server rewrite rules. The information I found was sparse. Maybe it can be done, as I did this a while ago and things change. I can only tell you what worked for me then and still works for me now.

publicPath

Inside your quasar.conf.js you can set up the publicPath. What this does is put the public path data from the publicPath variable in front of all your resource calls.

    build: {
      vueRouterMode: 'history',
      publicPath: 'app-extension-qmarkdown',

Notice the publicPath? This is for my component, QMarkdown, which lives at https://github.com/quasarframework/app-extension-qmarkdown. And, the github.io url would be this: https://quasarframework.github.io/app-extension-qmarkdown.

Using this publicPath allows me to develop locally and then, when I build the site, the publicPath is injected so resources can properly be found by the browser.

The 404 on Github.io

If you drop a 404.html into root of your SPA app, when a page is not found, it will be called. Since vue-router will be managing the routing, this 404.html page will be called for any presumably static page that doesn't exist (meaning, all your routes!).

I came up with a way to leverage this 404.html file. It took a while (over a week) to figure this all out and finalize it.

Basically, this is what your 404.html should look like:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />

  <title>404 Redirect</title>

  <script>
    sessionStorage.redirect = location.href;
  </script>

  <meta http-equiv="refresh" content="0;URL='/app-extension-qmarkdown'"></meta>
</head>

<body>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</body>


</html>

Notice the meta tag with URL. This needs to match your publicPath route in order for it to work.

You may also be wondering why there are all the spaces between the body tags. There was some issue with Internet Explorer. If the file was too small, it just wouldn't read it.

The Last Trick

The 404.html is running a snippet of JavaScript to put the current route into sessionStorage. This is key to getting this all to work. We have to use this sessionStorage to get back on track with vue-router.

In your index.template.html file, you can add the following between the body tags:

  <body>
    <script>
        (function(){
          let redirect = sessionStorage.redirect;
          delete sessionStorage.redirect;
          if (redirect && redirect !== location.href) {
            history.replaceState(null, null, redirect);
          }
        })();
      </script>
    <!-- DO NOT touch the following DIV -->
    <div id="q-app"></div>
  </body>

As you can see, sessionStorage is read, deleted and then history is put back in place. Now, vue-router can take over without issues occurring in the browser.

Final Words

The above happens so fast, you would never know what's happening behind the scenes.

It is my hope that this helps others leverage github.io in history mode, just as it has helped me.

Are you using Github.io for publishing your SPA? Let's us also know your experiences or give us feedback about this article. We'd love to hear from you.

Interested in Quasar? Here are some more tips and information:
More info: https://quasar.dev
GitHub: https://github.com/quasarframework/quasar
Getting Started: https://quasar.dev/start
Chat Server: https://chat.quasar.dev/
Forum: https://forum.quasar.dev/
Twitter: https://twitter.com/quasarframework
Donate: https://donate.quasar.dev

Quasar

One source code for all platforms simultaneously through Quasar CLI with all the latest and greatest best practices out of the box. Focus only on your app's features and forget about the boilerplate around it.

Discussion

markdown guide
 

Nice article. I'm looking at trying similar on Netlify.

So the publicPath variable is only necessary because you are hosting the site starting from a subpath instead of at the root?

 

Yes, it's because the path is more that the root path.