diagram.mmd — flowchart
Client Side Routing flowchart diagram

Client-side routing is the mechanism by which a JavaScript application matches the current URL to a component tree and renders it — all within the browser, without any server round-trip for each navigation.

The foundation of client-side routing is the browser's History API: pushState and replaceState update the URL bar and the session history stack without triggering a page reload, while the popstate event fires when the user navigates back or forward. Router libraries wrap these primitives and expose a declarative API for defining which component should render for each URL pattern.

When a navigation occurs, the router receives the new pathname and runs it through a route matching algorithm. Routes are typically defined as an ordered list of path patterns (e.g., /users/:id, /settings/*). The router tests each pattern in order and selects the first match. Named parameters like :id are extracted from the URL and passed as props or available via a hook. Nested routes allow layouts to be composed hierarchically — a shell layout renders at /app, and child routes render their content inside it without re-mounting the shell.

Once a match is found, the router checks whether the matched route's component is already loaded into the bundle or needs to be fetched (see Lazy Loading Components). Route guardsbeforeEach, canActivate, or loader functions — run next to check authentication, fetch required data, or redirect. If the guard passes, the matched component is rendered into the router outlet. The SPA Navigation Flow shows this full sequence end-to-end.

For developers, client-side routing also requires careful handling of the initial load: the server must serve the same index.html for all URL paths so the SPA can boot and take control of routing, rather than receiving a 404 for deep-linked URLs.

Free online editor
Edit this diagram in Graphlet
Fork, modify, and export to SVG or PNG. No sign-up required.
Open in Graphlet →

Frequently asked questions

Client-side routing is a JavaScript mechanism that maps the current URL to a component tree and renders it entirely within the browser. Navigation updates the URL via the History API (`pushState`) without triggering a server round-trip or full page reload.
The router holds an ordered list of path patterns (e.g. `/users/:id`, `/settings/*`). When the URL changes, the router tests each pattern in order and selects the first match. Named segments like `:id` are extracted and passed to the component. Nested routes let inner layouts compose inside outer shells without re-mounting the shared shell on every navigation.
Use client-side routing for applications where fast in-app navigation and rich interactivity outweigh the SEO and initial-load cost: dashboards, admin tools, and social apps. Use server-side routing (or a hybrid SSR framework like Next.js or Nuxt) when SEO or fast first-contentful-paint on every URL is critical, since pure SPAs require JavaScript to execute before any content is visible.
The most common mistake is failing to configure the server to return `index.html` for all routes, causing 404s on direct navigation or page refresh. Others include not using `key` props on route-level components (causing stale state between routes), missing route guards for authentication, and forgetting to manage scroll position on navigation.
mermaid
flowchart TD A[URL Change Event] --> B{Source of change?} B -- User click on link --> C[Intercept Click Event] B -- router.push called --> D[Programmatic Navigation] B -- Browser back/forward --> E[popstate Event Fired] C --> F[Call History.pushState] D --> F E --> G[Read Current Location] F --> G G --> H[Run Route Matching Algorithm] H --> I{Match found?} I -- No --> J[Render 404 Component] I -- Yes --> K[Extract URL Parameters] K --> L[Run Route Guards and Loaders] L --> M{Guard passes?} M -- No --> N[Redirect to Guard Target] M -- Yes --> O{Component chunk loaded?} O -- No --> P[Dynamic Import Chunk] P --> Q[Render Matched Component] O -- Yes --> Q style Q fill:#22c55e,color:#fff
Copied to clipboard