The arrival of modern web frameworks has changed the way developers think and build software. We can now use flexible frameworks (with really cool names) — such as Angular, React and Vue — to easily whip up appealing interfaces.
Some benefits of working with modern front-end frameworks include:
Each framework has a unique way of solving problems but the general concept of a framework regulates the fundamental similarities amongst them. In this article, we will look at client-side routing, its importance and Vue Router — our preferred router for Vue applications.
SPA’s are web applications that display dynamic content within the space of a single page throughout the duration of the interaction. SPA’s work by neatly replacing the user interface of the application as the user switches from page to page.
A SPA knows how to make these page transitions using a router. The router is responsible for the synchronicity between the URL address bar and the interface being displayed. In web development, there have been two fundamental methods for rendering content to the web browser:
With the server-side method, the client makes a request to a server whenever new content is expected. The obvious downside to this is it can be wastefully repetitive in its interaction with the back-end resource. The good side — it is great for SEO because crawler bots are supplied with content to index.
With the client-side method, the web application will initially request a page from the back-end server — index.html
— then after that first request, additional data will be fetched dynamically (using an [XHR](https://www.w3schools.com/xml/xml_http.asp)
object). The application’s further routing will be handled by client-side JavaScript.
Let’s define our subject of discussion — routers:
A router is a tool that synchronizes the currently displayed view with the address bar. In other words, it’s the component of a modern web application that triggers the update for the view when there has been a change to the URL address.
We will be considering Vue as the progressive JavaScript framework of interest. It has an official router module called Vue Router. This router is constantly being maintained by the same people who maintain the Vue framework.
Vue Router is the official router for Vue. It deeply integrates with Vue core to make building SPAs with Vue a breeze. Some features of Vue Router are:
Let’s find out some of the benefits of Vue Router by setting it up and working with it.
Although there are a number of ways to set up a Vue project, our preferred method for this tutorial is the vue-cli. The vue-cli gives us the benefit of being able to quickly scaffold and serve Vue projects. We are going to use the latest version of the tool (version 3) as at the time of writing this article — if you do not already have it installed, you can install it here.
We can create a new Vue project with this command:
vue create routerapp
You will be prompted to pick a preset, choose default (babel, eslint).
Let’s add Vue Router to our project:
npm install vue-router
Note: This would be
yarn add vue-router
if you use Yarn. If you prefer to use Vue via a script tag, you can include Vue Router with this script:<script src="https://unpkg.com/vue-router"></script>
We have successfully installed Vue Router but there is no way for Vue to know about its existence. We will explicitly tell Vue to use Vue Router in the src/main.js
file:
import Vue from 'vue' import App from './App.vue' import VueRouter from 'vue-router' import routes from './routes' Vue.use(VueRouter) const router = new VueRouter({ routes }) Vue.config.productionTip = false new Vue({ render: h => h(App), router }).$mount('#app')
Note: Your IDE might display an error if you try to save but this is only because we haven’t created the — routes — folder yet. We will create it next, so ignore the error for now.
We have included a reference to a folder — ./routes
— that hasn’t been created yet. This folder will contain a file where we will define the routes and the views they map to.
We called Vue.use()
and passed in the VueRouter
object so that we have access to the router in any component. Let’s create the routes
folder within the src
directory. We will also create an index.js
file within the src/routes
folder where our route definitions will be saved.
Open the src/routes/index.js
file and paste in the following snippet:
import Home from '../components/Home' import About from '../components/About' const routes = [ { path: '/', name: 'home', component: Home }, { path: '/about', name: 'about', component: About } ] export default routes
Note: Just as before, we have referenced a few files that are yet to be created. Ignore any lint errors for now. We will create these view files very soon.
In the code snippet above, we have defined a few routes and their views. We imported two component views (we will create these soon) and added them as components in the routes
array. This is how we define new routes with Vue Router.
Let’s create the Home
and About
components:
Home
component is the default component we want users to see on page loadAbout
component displays some information about the applicationCreate a home.vue
file within the components
directory and paste in the following snippet:
<template> <div class="home"> <h2>THIS IS THE HOME VIEW</h2> </div> </template> <script> export default { name: "home" }; </script> <style scoped> .home { width: 100%; height: 50vh; background: rgb(25, 169, 241); } h2 { padding: 15px 0px 0px 0px; margin: 0px; text-align: center; font-size: 24px; } </style>
Great, we’ve just defined the mark up for the homepage, now let’s create a — about.vue
— file within the components
directory and paste in the following content:
<template> <div class="about"> <h2>THIS IS THE ABOUT VIEW</h2> </div> </template> <script> export default { name: "about" }; </script> <style scoped> .about { width: 100%; height: 50vh; background: rgb(243, 245, 145); } h2 { padding: 15px 0px 0px 0px; margin: 0px; text-align: center; font-size: 24px; } </style>
We have built both components but for us to see Vue Router’s smooth transitioning in action, we have to use the <router-view/>
tag. When this tag is defined, it automatically controls which view is displayed depending on the URL address bar. Where do we put this tag?
Let’s open up the parent component — src/App.vue
— and edit it so that it has two links for both components and displays the proper view using <router-view/>.
Open up the file and paste in the following snippet:
<template> <div id="app"> <nav> <router-link to="/">Home</router-link> <router-link to="/about">About</router-link> </nav> <router-view/> </div> </template> <script> export default { name: "app" }; </script> <style> #app { max-width: 896px; margin: 0 auto; } nav { padding: 10px; border: 1px solid grey; } nav a { color: white; padding: 5px; background: grey; border-radius: 3.5px; text-decoration: none; } a:first-child { margin-right: 15px; } </style>
Let’s test the application now. Navigate into the src
directory using the terminal and serve the application:
$ cd src $ vue serve
The last command will start the development server and render the application on the local address — http://localhost:8080/ — let’s visit it on our browser:
In the screen recording above, we can see how the application toggles between the home and about pages without causing a reload to the browser’s window. This is the power of a router in a modern web framework. Let’s look at some other functions and features of Vue Router.
You’ll notice that there’s a “#” in the URL address bar of the application. This is because, by default, Vue Router uses the URL hash to simulate a full URL so that the page won’t be reloaded when the URL changes. We can toggle the mode and change it to history mode which leverages the history.pushState
API to achieve URL navigation without a page reload.
Let’s switch to history mode by updating the code in the src/main.js
file:
import Vue from 'vue' import App from './App.vue' import VueRouter from 'vue-router' import routes from './routes' Vue.use(VueRouter) const router = new VueRouter({ mode: 'history', // add this routes }) Vue.config.productionTip = false new Vue({ render: h => h(App), router }).$mount('#app')
Great, now let’s head over to the web browser and we can see that the “#” is gone and history mode is activated:
We’ve barely explored the functions and features of Vue Router but here are a few other features for the curious:
Let’s take a look at some alternatives to Vue Router in the next section.
Sometimes, you might want to use a different router for your Vue application. When that is the case, here are a few alternatives worth considering:
Voie, as defined on the official npm page, is a simple router for building robust SPAs in Vue. Unlike Vue Router which is organized around URLs, Voie is organized around states. Voie-based apps are basically finite-state machines — the state is simply a named logical “place” within your application.
Each state can optionally have a:
States are organized into hierarchies: child states will inherit parameters and data from the parent state. If the child state has a component, it will be rendered at the location specified by the parent (or nearest ancestor) state denoted by <v-view>
directive.
Let’s take a look at this example:
Note: Voie is still undergoing active development so issues reported issues will be fixed as the development progresses.
Voie can be installed with npm using the following command:
npm i --save voie
Let’s take a look at this example:
app.add('user', { path: '/user/:userId', redirect: 'user.dashboard', // specify "default" sub-state enter: (ctx) => { // can return a Promise return fetch('/user/' + ctx.params.userId) .then(res => res.json()) .then(data = ctx.data.user = data); }, component: { template: '<div class="user-layout"><v-view></v-view></div>' } }); app.add('user.dashboard', { component: { template: '<h1>Hello, {{ user.name }}!</h1>' } });
In the snippet above, visiting /user/123
would fetch a user with id 123
from a server and then render the following markup (assuming the user has the name “Alice”):
<div class="user-layout"> <h1>Hello, Alice!</h1> </div>
Note: fragment instances are not supported as components. In other words, make sure all components contain a single top-level element without flow control directives (
v-if
,v-for
, etc.)
Visit the official npm page to learn more concepts about other Voie, including:
A significant time in Vue’s development curve as a web framework was when Laravel started shipping with a front-end boilerplate containing Bootstrap and Vue. This led to the adoption of Vue as the preferred front-end framework of many Laravel developers. That being said, Vue-routisan is a Vue routing system based on the Laravel routing system.
We can install Vue-routisan with npm using the following command:
npm install vue-routisan
The view()
method receives the path
and component
route options respectively. If you defined the view resolver, you may directly specify the name of the component:
Route.view('/', 'Home');
Without the view resolver, it would be:
import Home from './views/Home'; Route.view('/', Home);
The view resolver allows the view()
method to automatically require components for your routes. This saves you from having repetitive import
s and require
s when defining routes. The view resolver is optional. If you choose to not configure it, you can import
a component and pass it directly as the 2nd parameter of the view()
method:
import Route from 'vue-routisan'; Route.setViewResolver((component) => { return require('./views/' + component).default; });
The name()
method sets the name
option on the route instance:
Route.view('/user/profile', 'Profile').name('profile');
The children()
method sets the children
option on the route instance:
Route.view('/user', 'User').children(() => { Route.view('', 'UserList'); Route.view(':id', 'UserDetails'); Route.view(':id/edit', 'UserEdit'); });
Visit the official npm page to learn about other Vue-routisan concepts including:
Vue-route is a routing directive for Vue.js inspired by ng-view.
It allows you to declare your routes on the $root
Vue object:
var root = new Vue({ el: 'body', routes: { '/home': { componentId: 'fg-home', isDefault: true }, '/items/:item': { componentId: 'fg-item', afterUpdate: 'updateHeader', data: { defaultColor: '#3453DD' } }, options: { hashbang: true } } });
Then you can reference it with minimal markup:
<body> <div v-route></div> </body>
npm i vue-route --save
var Vue = require('vue'), route = require('vue-route'); Vue.use(route);
<div v-route></div>
in your main template.$root
VM of your app.If you want to add custom transitions between your pages, it’s recommended to put them on each page’s component template. Putting anything on the v-route
element itself will only be active if you change this element (for instance with a v-if
directive). Following the example, that would be:
<div class="Home" v-transition="homeTransition">...</div>
Visit the official npm page to learn about other Vue-route concepts including:
In this article, we learned some of the differences between client-side and server-side rendered applications. We also saw some advantages of client-side routing and how it can augment the performance of our web applications.
We further went on to learn about Vue and Vue Router (the official router for Vue) in addition to alternatives to Vue Router. If you’ve been looking to explore an alternative to Vue Router, you should try getting acquainted with one of the options listed above.
Debugging Vue.js applications can be difficult, especially when there are dozens, if not hundreds of mutations during a user session. If you’re interested in monitoring and tracking Vue mutations for all of your users in production, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording literally everything that happens in your Vue apps, including network requests, JavaScript errors, performance problems, and much more. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.
The LogRocket Vuex plugin logs Vuex mutations to the LogRocket console, giving you context around what led to an error and what state the application was in when an issue occurred.
Modernize how you debug your Vue apps — start monitoring for free.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowSimplify component interaction and dynamic theming in Vue 3 with defineExpose and for better control and flexibility.
Explore how to integrate TypeScript into a Node.js and Express application, leveraging ts-node, nodemon, and TypeScript path aliases.
es-toolkit is a lightweight, efficient JavaScript utility library, ideal as a modern Lodash alternative for smaller bundles.
The use cases for the ResizeObserver API may not be immediately obvious, so let’s take a look at a few practical examples.
2 Replies to "Router options compared: Vue Router, Voie, Vue-routisan and Vue-route"
i got the problem ::
This relative module was not found:
* ./routes in ./src/main.js
You can create a folder called `routes` in the `src` directory. Then create a file called `index.js` within the `src/routes` directory and paste in the following code:
“`import Home from ‘../components/Home’
import About from ‘../components/About’
const routes = [
{
path: ‘/’,
name: ‘home’,
component: Home
},
{
path: ‘/about’,
name: ‘about’,
component: About
}
]
export default routes“`