JavaScript Routing with Hash and History API

February, 25th 2025 2 min read

Routing in JavaScript is about updating the URL and displaying the corresponding content without reloading the page. This improves user experience by preventing unnecessary refreshes and preserving state. The two primary routing techniques used in Single Page Applications (SPAs) are hash-based routing and history-based routing.

1. Hash-Based Routing

Hash routing uses the URL fragment (#something) to control navigation without triggering a full page reload.

How It Works

  • The part after # never triggers a server request.
  • JavaScript listens for hashchange events and updates the UI accordingly.
  • Ideal for simple SPAs because it needs no server configuration.

Basic Example

html
<ul>
  <li><a href="#/home">Home</a></li>
  <li><a href="#/about">About</a></li>
</ul>
<div id="app"></div>

<script>
  const routes = {
    '/home': '<h2>Home Page</h2>',
    '/about': '<h2>About Page</h2>',
  };

  function routerView() {
    const hash = location.hash.substring(1) || '/home';
    document.getElementById('app').innerHTML = routes[hash] || '<h2>404 Not Found</h2>';
  }

  window.addEventListener('DOMContentLoaded', routerView);
  window.addEventListener('hashchange', routerView);
</script>

Pros and Cons

Pros:

  • No server config needed
  • Works everywhere
  • Easy to implement

Cons:

  • URL looks less clean (/#/about)
  • Not ideal for SEO

2. History API Routing

The History API uses clean URLs like /home without page reloads.

How It Works

  • Use history.pushState() to change the URL.
  • Listen for popstate events (back/forward buttons).
  • Requires server configuration (redirect all requests to index.html).

Basic Example

html
<ul>
  <li><a href="/home" class="nav-link">Home</a></li>
  <li><a href="/about" class="nav-link">About</a></li>
</ul>
<div id="app"></div>

<script>
  const routes = {
    '/home': '<h2>Home Page</h2>',
    '/about': '<h2>About Page</h2>',
  };

  function routerView() {
    const path = location.pathname;
    document.getElementById('app').innerHTML = routes[path] || '<h2>404 Not Found</h2>';
  }

  document.querySelectorAll('.nav-link').forEach(link => {
    link.addEventListener('click', event => {
      event.preventDefault();
      const href = link.getAttribute('href');
      history.pushState({}, '', href);
      routerView();
    });
  });

  window.addEventListener('popstate', routerView);
  window.addEventListener('DOMContentLoaded', routerView);
</script>

Pros and Cons

Pros:

  • Clean, SEO-friendly URLs
  • Matches modern SPA frameworks (React Router, Vue Router)

Cons:

  • Requires server rewrite rules
  • Slightly more complex

⚖️ Hash vs History: Quick Comparison

FeatureHash RoutingHistory API
URL Style/#/route/route
Requires Server Config❌ No✅ Yes
SEO Friendly❌ No✅ Yes
Browser SupportExcellentExcellent
Easiest for Beginners✅ Yes❌ No

Summary

To build client-side routing:

  1. Intercept navigation to avoid page reloads
  2. Update the URL using hash or History API
  3. Render content dynamically based on the current route
  4. Listen for changes (hashchange or popstate)

Mastering both routing styles prepares you for building full-featured SPAs and understanding popular frameworks’ internals.