How we handle navigation and URL changes in web apps plays a pivotal role in UX, performance and SEO. Let’s compare server-side routing and client-side routing.
In the realm of web development, the way we handle navigation and URL changes plays a pivotal role in user experience, performance and search engine optimization. Understanding the difference between server-side and client-side routing is fundamental for developers. In this article, we’ll delve into the specifics of these two popular routing techniques and compare their pros and cons.
First and foremost: let’s define routing for those who may be new to the concept.
In web development, routing often refers to splitting an application’s UI based on rules derived from the browser URL. Imagine clicking a link and having the URL go from https://website.com
to https://website.com/about/
.
That’s routing.
When we visit the /
path of a website, we intend to visit the home route of that website. If we visit /about
, we want to render the About page, and so on.
Many applications can technically be written without routing but this can get messy as an application grows. Defining routes in an application is useful since one can separate different areas of an app and protect areas of the app based on certain rules.
Routing is often categorized into two main buckets:
In a server-driven application, requests to a URL often follow a pattern:
Server-side routing is often set up to retrieve and return different information depending on the incoming URL. Writing server-side routes with Express.js generally looks like the following:
const express = require("express");
const router = express.Router();
// define the about route
router.get("/about", function (req, res) {
res.send("About us");
});
Or using Ruby on Rails, a similar route definition might look like this:
# routes.rb
get '/about', to: 'pages#about'
# PagesController.rb
class PagesController < ActionController::Base
def about
render
end
end
Whether it’s Express.js, Ruby on Rails, or any other server-side framework, the pattern often remains the same. The server accepts a request and routes it to a controller, and the controller runs a specific action (e.g., returns specific information), depending on the path and parameters.
In applications employing client-side routing, the server initially provides a single HTML file, irrespective of the URL path. This “shell” is then enriched and manipulated by JavaScript running in the browser. Subsequent navigation between different parts of the app does not send new requests to the server but rather modifies the displayed content based on the loaded JavaScript and data.
These are characteristic of single-page applications (SPAs)—web apps that load only once (i.e., the server provides a single template) and JavaScript is used to dynamically render different pages.
The flow for client-side routing usually looks like the following:
With client-side routing, while the initial load might seem slower because the entire app (or large parts of it) gets loaded, subsequent navigations are swift and seamless, as they don’t require round-trips to the server.
Client-side routing can be implemented using various libraries and frameworks. For instance, React Router is a popular client-side routing library for React applications:
import * as React from "react";
import { createRoot } from "react-dom/client";
import {
createBrowserRouter,
RouterProvider,
Route,
Link,
} from "react-router-dom";
const router = createBrowserRouter([
{
path: "/",
element: (
<div>
<h1>Hello World</h1>
<Link to="about">About Us</Link>
</div>
),
},
{
path: "about",
element: <div>About</div>,
},
]);
createRoot(document.getElementById("root")).render(
<RouterProvider router={router} />
);
While for Vue applications, Vue Router is the recommended client-side routing library.
const Home = { template: "<div>Home</div>" };
const About = { template: "<div>About</div>" };
const routes = [
{ path: "/", component: Home },
{ path: "/about", component: About },
];
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
routes,
});
Both server-side and client-side routing have their places in modern web development. The choice between them often comes down to the specific needs of the project.
In server-side routing:
While in client-side routing:
If search engine optimization and initial page load speed are critical, server-side routing might be the way to go. On the other hand, if the priority is to provide a dynamic, app-like user experience, then client-side routing in a SPA could be the ideal choice.
In today’s versatile tech landscape, hybrid solutions are also emerging that combine the best of both worlds, such as Next.js for React or Nuxt.js for Vue, which offer server-side rendering for SPAs, thus addressing many traditional drawbacks of client-side routing. We’ll talk about these frameworks in more detail in upcoming articles!
Ultimately, understanding the nuances, strengths and weaknesses of both the server-side and client-side routing methods will empower you to make informed decisions that best suit your application’s needs.
Hassan is a senior frontend engineer and has helped build large production applications at-scale at organizations like Doordash, Instacart and Shopify. Hassan is also a published author and course instructor where he’s helped thousands of students learn in-depth frontend engineering skills like React, Vue, TypeScript, and GraphQL.