Using Vue Router’s History Mode.
Tags: vue, webdev, programming, javascript
Published: 2021-01-25 23:18:27

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

Vue Router is a URL router that maps URLs to components.

In this article, we’ll look at how to use Vue Router’s history mode.

HTML5 History Mode
==================

The default mode for Vue Router is hash mode. It uses a URL hash to simulate a full URL so that the page won’t be reloaded when the URL changes.

We can set Vue Router to history mode to get rid of the hash. It uses `history.pushState` API to let us navigate URLs without a page reload.

For example, we can enable history mode as follows:

`src/index.js` :

```
const Foo = { template: "<div>foo</div>" };  
const Bar = { template: "<div>bar</div>" };  
const routes = [  
  {  
    path: "/foo",  
    component: Foo  
  },  
  {  
    path: "/bar",  
    component: Bar  
  }  
];

const router = new VueRouter({  
  mode: "history",  
  routes  
});

new Vue({  
  el: "#app",  
  router  
});
```

`index.html` :

```
<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://unpkg.com/vue/dist/vue.js"></script>  
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <router-view></router-view>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>
```

Then when we go to `/foo` and `/bar` , we’ll see `foo` and `bar` displayed respectively. Now we don’t need to add a hash sign in front of the URL anymore.

Server Configuration
====================

The issue with history mode is that we have to configure our server to display our app whenever the user navigates to the folder in our server.

This is because if we didn’t configure our server, we’ll get a 404 error if we go directly to the URL from the browser.

To fix this, we need to redirect to `index.html` if it doesn’t match any assets uploaded to the server that we want to load.

We can use the following configure in Apache:

```
<IfModule mod_rewrite.c>  
  RewriteEngine On  
  RewriteBase /  
  RewriteRule ^index.html$ - [L]  
  RewriteCond %{REQUEST_FILENAME} !-f  
  RewriteCond %{REQUEST_FILENAME} !-d  
  RewriteRule . /index.html [L]  
</IfModule>
```

This configuration assumes that the code is in the root folder. If it’s in a subfolder, we can change `RewriteBase /` with `RewriteBase /subfolder-name/` .

For Nginx, it’s simpler:

```
location / {  
  try_files $uri $uri/ /index.html;  
}
```

Again, we can replace `/` with the subfolder if the code is in a subfolder.

We should add a 404 route to our app since how 404 errors won’t be displayed.

We can add one as follows:

`src/index.js` :

```
const Foo = { template: "<div>foo</div>" };  
const Bar = { template: "<div>bar</div>" };  
const NotFound = { template: "<div>not found</div>" };  
const routes = [  
  {  
    path: "/foo",  
    component: Foo  
  },  
  {  
    path: "/bar",  
    component: Bar  
  },  
  { path: "*", component: NotFound }  
];

const router = new VueRouter({  
  mode: "history",  
  routes  
});

new Vue({  
  el: "#app",  
  router  
});
```

`index.html` :

```
<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://unpkg.com/vue/dist/vue.js"></script>  
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <router-view></router-view>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>
```

With Node.js, the easiest way to serve a Vue app with history mode set by using Express and the `connect-history-api-fallback` middleware as follows:

`server.js` :

```
const express = require('express');  
const history = require('connect-history-api-fallback');

const app = express();  
app.use(history());  
app.use(express.static('src'));

app.get('/', (req, res) => {  
  res.sendFile('src/index.html');  
});

app.listen(3000, () => console.log('server started'));
```

Then the Vue app files can be stored in the `src` folder.

In the code above, the code:

```
{ path: "*", component: NotFound }
```

is the catch-all route for anything other than `foo` and `bar` and maps to the `NotFound` component.

Conclusion
==========

We can enable the Vue Router’s history mode to eliminate the hash from our app’s URLs.

However, we have to redirect our app to `index.html` since we don’t want users to see errors when they go the URLs by entering it or refreshing the page.

We can do this with any web server. Then we have to add a catch-all route to display something when it doesn’t match any routes.