跪拜 Guibai
← All articles
Frontend

How the Humble URL Hash Fragment Became the Foundation of Single-Page Apps

By 东风破_ ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Hash routing is still the fastest path to client-side navigation when you can't touch the server—static sites, Electron apps, and embedded webviews all rely on it. Understanding the `hashchange` event and the routing table pattern demystifies what React Router and Vue Router actually do under the hood.

Summary

Traditional multi-page applications reload the full HTML document on every link click, causing a white flash and re-rendering identical headers, nav bars, and footers. The core insight behind single-page apps is that the URL's hash fragment—originally designed for in-page anchor jumps—changes without triggering an HTTP request. By listening for the `hashchange` event and mapping hash values to DOM replacement callbacks, a developer can build client-side routing with zero server configuration.

A hand-written `HashRouter` class in vanilla JavaScript distills this pattern to three essential pieces: a routing table that maps hash strings to render functions, a `hashchange` listener that fires on every navigation, and a single mount point where content gets swapped. The same architecture underpins every major framework router, from React Router's `<HashRouter>` to Vue Router's `createWebHashHistory`.

The trade-off is real: hash URLs look ugly, break SEO, and hide route state from the server. Those limitations directly motivated the History API and server-side rendering strategies that came later, but the hash-based approach remains the simplest way to add routing to a static front end.

Takeaways
Clicking a link in a traditional multi-page app triggers a full HTTP request and re-renders the entire DOM, even when 90% of the page structure is identical.
The hash fragment of a URL—everything after `#`—is never sent to the server, so changing it does not cause a page refresh.
Browsers fire a `hashchange` event whenever the hash changes, which a script can use to swap content without a network round-trip.
A minimal front-end router needs only three things: a routing table (hash-to-callback map), a `hashchange` listener, and a DOM mount point for content replacement.
Inside `addEventListener` callbacks, `this` defaults to the event target (`window`), so methods must be explicitly bound to the router instance with `.bind(this)`.
Hash routing's downsides—ugly URLs, poor SEO, invisible server-side state—led directly to the History API (`pushState`/`popstate`) and modern SSR strategies.
Conclusions

The jump from anchor links to application routing is a case study in repurposing a browser primitive far beyond its original intent—hash fragments were meant for document navigation, not application state.

Frameworks like React Router add a lot of ceremony, but the underlying mechanism is so simple it fits in a dozen lines of vanilla JS; the real complexity comes from nested routes, guards, and lazy loading, not the core pattern.

The `this` binding problem in `addEventListener` is a small but telling detail: it's exactly the kind of JavaScript quirk that framework abstractions hide, and exactly the kind that trips up developers who skip the fundamentals.

Concepts & terms
Hash fragment
The portion of a URL following the `#` symbol. Originally designed for in-page anchor navigation, it is never sent to the server and can be changed without triggering a page reload, making it the foundation of hash-based client-side routing.
hashchange event
A browser event that fires whenever the hash fragment of the current URL changes. Front-end routers listen for this event to detect navigation and swap page content accordingly.
Routing table
A data structure—typically an object or map—that associates URL patterns (like hash strings) with callback functions that render the corresponding page content into a mount point.
Mount point
A single DOM element (often a `<div>` with an id like `#container`) that serves as the target for all dynamic content replacement in a single-page application.
Single Page Application (SPA)
A web application that loads a single HTML document and dynamically updates content in place as the user navigates, rather than fetching entirely new pages from the server.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗