JavaScript: using the History API and the Fetch API to handle routing in a web app

JavaScript: using the History API and the Fetch API to handle routing in a web app

In modern web development, creating single-page applications (SPAs) that provide a smooth and seamless user experience is a common goal. One essential aspect of SPAs is the ability to handle multiple routes or URLs without refreshing the entire page. This can be achieved by utilizing the History API and the Fetch API in JavaScript.

In modern web development, creating single-page applications (SPAs) that provide a smooth and seamless user experience is a common goal. One essential aspect of SPAs is the ability to handle multiple routes or URLs without refreshing the entire page. This can be achieved by utilizing the History API and the Fetch API in JavaScript. In this article, we will explore how to use these APIs to create multiple routes in a JavaScript web app.

The History API allows us to interact with the browser's session history, enabling us to navigate between different states of the application without triggering a full page reload. On the other hand, the Fetch API provides a powerful and flexible way to make HTTP requests from the browser. By combining these two APIs, we can dynamically load content based on different routes and enhance the user experience.

Setting Up the HTML Structure

To begin, let's create a basic HTML structure for our web app. We'll need a container element to load the content dynamically based on the routes. Here's a simple example:


<!DOCTYPE html>
<html>
<head>
    <title>App</title>
</head>
<body>
    <header>
        <nav>
            <ul>
                <li><a href="/">Home</a></li>
                <li><a href="/about">About</a></li>
                <li><a href="/contact">Contact</a></li>
            </ul>
        </nav>
    </header>

    <main>
        <div id="content"></div>
    </main>

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

Handling Navigation

Next, we need to handle the navigation within our application. We'll utilize the popstate event from the History API to detect when the user navigates back or forward. Add the following code to your app.js file:


document.addEventListener('DOMContentLoaded', () => {
    const contentDiv = document.getElementById('content');

    function handleNavigation(route) {
        // Use Fetch API to load content dynamically based on the route
        fetch(route)
            .then(response => {
		 if(!response.ok) {
                    throw new Error('Not Found');
                 }	
		 return response.text();
	   }).then(data => {
                contentDiv.innerHTML = data;
            })
            .catch(error => {
                console.error('Error:', error);
            });
    }

    function navigate(event) {
        event.preventDefault();
        const route = event.target.getAttribute('href');
        handleNavigation(route);
        // Update browser history without triggering a full page reload
        history.pushState({}, '', route);
    }

    // Attach click event listeners to navigation links
    const navLinks = document.querySelectorAll('nav a');
    navLinks.forEach(link =>, {
        link.addEventListener('click', navigate, false);
    });

    // Handle initial page load or when the user navigates back/forward
    window.addEventListener('popstate', () => {
        handleNavigation(window.location.pathname);
    });
});

Implementing Server-Side Routing

At this point, we have set up the client-side functionality to handle navigation, but we also need to configure the server-side routing to serve the appropriate content. This step depends on the server framework or technology you are using. For simplicity, we'll demonstrate a basic Express.js setup:


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

// Serve static files
app.use(express.static('public'));

// Define routes
app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

app.get('/:page', (req, res) => {
    const htmlFile = `${req.params.page}.html`;
    try {
    	res.sendFile(path.join(__dirname, 'public', htmlFile));
    } catch(err) {
        res.sendStatus(404);
    }
});

// Start the server
app.listen(3000, () => {
    console.log('Server listening on port 3000');
});

Now, if you open your web app in a browser and click on the navigation links, you should see the content being loaded dynamically without a full page reload. The browser's URL will also update accordingly.

Remember that the implementation may vary depending on the server-side technology you are using, but the core concept of utilizing the History API and Fetch API remains the same. Feel free to extend and customize this approach to suit your specific application requirements.