Learn how to build and implement a client-side routing system using JavaScript History API to easily work with a framework routing library.

In this article, we will build a client-side routing system. Client-side routing is a type of routing where users navigate through an application where no full page reload occurs even when the page’s URL changes — instead, it displays new content.

To build this, we’ll need a simple server that will serve our index.html file. Ready? Let’s begin.

First, set up a new node.js application and create the project structure:

npm init -y
npm install express morgan nodemon --save
touch server.js
mkdir public && cd public
touch index.html && touch main.js file
cd ..

The npm init command will create a package.json file for our application. We’ll install Express and Morgan , which will be used in running our server and logging of our routes.

We’ll also create a server.js file and a public directory where we will be writing our views. Nodemon will restart our application once we make any change in our files.

Setting up the server

Let’s create a simple server using Express by modifying the server.js file:

const express = require('express');
const morgan = require('morgan');
const app = express();

app.use(morgan('dev'));
app.use(express.static('public'))

app.get('*', (req, res) => {
    res.sendFile(__dirname + '/public/index.html')
})
app.listen(7000, () => console.log("App is listening on port 7000"))

Now we can start our application by running nodemon server.js. Let’s create a simple boilerplate for our HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>Javascript Routing</h1>
    <div id="app">
    </div>

    <script src="main.js"></script>
</body>
</html>

Here, we’ll link the main.js file so that we can manipulate the DOM at any point in time.

Implementing the routing system

Let’s head over to the main.js file and write all of our router logic. All our codes will be wrapped in the window.onload so that they only execute the script once the webpage has completely loaded all of its content.

Next, we’ll create a router instance that’s a function with two parameters. The first parameter will be the name of the route and the second will be an array which comprises all our defined routes. This route will have two properties: the name of the route and the path of the route.

window.onload = () => {
// get root div for rendering
    let root = document.getElementById('app');

  //router instance
    let Router = function (name, routes) {
        return {
            name,
            routes
        }
    };

 //create the route instance
    let routerInstance = new Router('routerInstance', [{
            path: "/",
            name: "Root"
        },
        {
            path: '/about',
            name: "About"
        },
        {
            path: '/contact',
            name: "Contact"
        }
    ])

}

We can get the current route path of our page and display a template based on the route.location.pathname returns the current route of a page, and we can use this code for our DOM:

 let currentPath = window.location.pathname;
    if (currentPath === '/') {
        root.innerHTML = 'You are on Home page'
    } else {
        // check if route exist in the router instance 
        let route = routerInstance.routes.filter(r => r.path === currentPath)[0];
        if (route) {
            root.innerHTML = `You are on the ${route.name} path`
        } else {
            root.innerHTML = `This route is not defined`
        }
    }

We’ll use the currentPath variable to check if a route is defined in our route instance. If the route exists, we’ll render a simple HTML template. If it doesn’t, we’ll display This route is not defined on the page.

Feel free to display any form of error of your choice. For example, you could make it redirect back to the homepage if a route does not exist.

Adding router links

For navigation through the pages, we can add router links. Just like with Angular, you can pass a routerLink that will have a value of the path you want to navigate to. To implement this, let’s add some links to our index.html file :

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <nav>
        <button router-link="/">Home</button>
        <button router-link="/about">About</button>
        <button router-link="/contact">Contact</button>
        <button router-link="/unknown">Error</button>
    </nav>
    <h1>Javascript Routing</h1>
    <div id="app">
    </div>

    <script src="main.js"></script>
</body>
</html>

Notice the router-link attribute that we passed in — this is what we will be using for our routing.

We’ll create a variable store all of router-links and store it in an array:

let definedRoutes = Array.from(document.querySelectorAll('[router-link]'));

After storing our router-links in an array, we can iterate through them and add a click event listener that calls the navigate() function:

 //iterate over all defined routes
    definedRoutes.forEach(route => {
        route.addEventListener('click', navigate, false)
    })

#javascript #api #web-development #programming #developer

Building and implementing a JavaScript Router using History API
14.30 GEEK