Welcome back, future Senior React Architects! In our previous chapters, we laid the groundwork for building robust React applications. We explored component composition, state management, and the core principles that make React so powerful. Now, it’s time to tackle one of the most critical decisions in frontend system design: how your application gets rendered and delivered to the user’s browser.

This chapter will take you on a journey through the fundamental rendering strategies: Client-Side Rendering (CSR), often synonymous with Single Page Applications (SPAs), Server-Side Rendering (SSR), and Static Site Generation (SSG). Understanding these approaches isn’t just about knowing acronyms; it’s about making informed architectural choices that profoundly impact your application’s performance, search engine optimization (SEO), user experience, and even your team’s development workflow. By the end of this chapter, you’ll have a clear mental model for each strategy, understand their trade-offs, and be ready to pick the right tool for the right job.

Before we dive in, make sure you’re comfortable with basic React component creation, props, state, and the idea of a JavaScript build process. If you’ve been following along, you’re perfectly primed for this next step! Let’s get rendering!


Core Concepts: Understanding How the Web Renders

At its heart, rendering is the process of turning your code into visible pixels on a user’s screen. The “where” and “when” this transformation happens define our rendering strategies. Let’s break them down.

1. Client-Side Rendering (CSR) / Single Page Applications (SPA)

Imagine you’re ordering a custom-built computer online. With Client-Side Rendering, the website initially sends you an empty box (a minimal HTML file) and a detailed instruction manual (your JavaScript bundle). Your browser (the “client”) then reads the manual, goes out to fetch all the necessary parts (data from APIs), assembles the computer (renders the UI), and makes it functional. All the heavy lifting of building the interface happens directly in the user’s browser.

What it is:

A Single Page Application (SPA) loads a single HTML page and dynamically updates content using JavaScript. The initial HTML file is often quite bare, primarily serving as a container for your React application.

Why it’s important:

SPAs excel at delivering rich, app-like experiences. Once the initial load is complete, navigating between different sections of the application is typically very fast because the browser doesn’t need to request a brand-new HTML page from the server for every interaction. Think of Gmail, Google Docs, or Trello – these are classic SPAs.

How it functions:

  1. Initial Request: The user’s browser requests the index.html file from the server.
  2. Empty Shell: The server responds with a minimal index.html that contains a <div id="root"></div> (or similar) and links to your JavaScript bundles.
  3. JavaScript Download & Execution: The browser downloads the JavaScript bundles (your React app code).
  4. Data Fetching: The JavaScript executes, fetching data from APIs.
  5. Rendering: React uses this data to build the UI and injects it into the #root div.
  6. Interactivity: The application becomes fully interactive. Subsequent navigation within the app is handled by React, updating the DOM directly without full page reloads.

Let’s visualize this flow:

flowchart TD A["User"] -->|"1. Request index.html"| B("Browser") B -->|"2. Fetches index.html (empty)"| C["Web Server"] C -->|"3. Sends index.html + JS links"| B B -->|"4. Downloads JS Bundle"| C B -->|"5. Executes JS (React App)"| D["Client-side JavaScript"] D -->|"6. Fetches Data (APIs)"| E["Backend APIs"] E -->|"7. Returns Data"| D D -->|"8. Renders UI into DOM"| F["DOM"] F -->|"\1"| D

Pros and Cons of SPAs:

Pros:

  • Rich User Experience: Feels fast and fluid after the initial load, like a native application.
  • Reduced Server Load: The server primarily serves static assets (HTML, JS, CSS) and API data, offloading rendering work to the client.
  • Easier API Integration: Naturally separates frontend and backend development, as the frontend consumes APIs.

Cons:

  • Slow Initial Load (Time to Interactive - TTI): Users see a blank page or spinner until all JavaScript is downloaded, parsed, and executed, and data is fetched.
  • Poor SEO (Historically): Search engine crawlers struggled with JavaScript-heavy sites that didn’t have content in the initial HTML. While modern crawlers are better, it can still be a concern for content-heavy sites.
  • Large JavaScript Bundles: All application logic needs to be downloaded upfront, potentially leading to large bundle sizes and slower initial load times, especially on mobile networks.
  • Requires JavaScript: If a user has JavaScript disabled, the application won’t render.

2. Server-Side Rendering (SSR)

If CSR is like getting an empty computer box and instructions, SSR is like getting a fully assembled, ready-to-use computer delivered to your door. The server does all the initial assembly (rendering the UI) before it even leaves the factory, so you can start using it immediately.

What it is:

With Server-Side Rendering, the server processes your React components and generates the complete HTML for the page on each request. This fully formed HTML is then sent to the browser.

Why it’s important:

SSR addresses the primary drawbacks of SPAs: slow initial load and SEO. By sending pre-rendered HTML, users see content much faster, and search engine crawlers have immediate access to the page’s content. This is crucial for content-driven websites, e-commerce, and blogs.

How it functions:

  1. Initial Request: The user’s browser requests a page URL.
  2. Server-side React Execution: The server (running Node.js, for example) receives the request. It then executes your React application code, fetches any necessary data, and renders the components into a complete HTML string.
  3. HTML Response: The server sends this fully formed HTML string back to the browser.
  4. Fast First Paint: The browser receives the HTML and immediately displays the content. The user sees meaningful content very quickly (Fast First Contentful Paint - FCP).
  5. JavaScript Download & Hydration: While the user sees the content, the browser downloads the JavaScript bundles. Once downloaded, React “hydrates” the pre-rendered HTML, attaching event listeners and making the application interactive. This process transforms the static HTML into a fully functional SPA.

Let’s visualize this flow:

flowchart TD A["User"] -->|"1. Request Page URL"| B("Browser") B -->|"2. Request HTML"| C("Web Server") C -->|"3. Executes React App & Fetches Data"| D("Backend APIs") D -->|"4. Returns Data"| C C -->|"5. Generates Full HTML String"| C C -->|"6. Sends HTML + JS Bundle"| B B -->|"7. Displays HTML (Fast FCP)"| E("DOM") B -->|"8. Downloads JS Bundle"| C B -->|"9. React Hydrates DOM"| F("DOM")

Pros and Cons of SSR:

Pros:

  • Improved Initial Load (FCP): Users see content much faster because the HTML is ready on arrival.
  • Better SEO: Search engines can easily crawl and index the pre-rendered content.
  • Graceful Degradation: Content is visible even if JavaScript fails or is disabled (though interactivity is lost).

Cons:

  • Increased Server Load: The server has to render the React application for every request, which consumes CPU and memory. This can be costly at high traffic volumes.
  • Slower Time to Interactive (TTI) compared to subsequent SPA loads: While FCP is fast, the page isn’t interactive until hydration completes, which still requires downloading and executing JavaScript.
  • Complex Setup: Historically, setting up SSR involved more complex build configurations. Frameworks like Next.js (version 14.x+, using React 18+ features) have simplified this significantly, making it a standard practice.
  • “Flash of Unstyled Content” (FOUC) or “Flash of Unhydrated Content”: If the client-side JavaScript takes too long to load or there’s a mismatch between server and client rendering, users might experience visual glitches during hydration.

Modern SSR with Next.js (2026 Context)

Next.js is the leading framework for building React applications that leverage SSR and SSG. With its App Router (introduced in Next.js 13, now mature in 14.x and beyond), it embraces React 18’s Server Components and streaming capabilities, allowing for even finer-grained control over what renders on the server and what hydrates on the client. This allows for partial hydration and improved performance, which we’ll explore in more detail in Chapter 5.

3. Static Site Generation (SSG)

If SSR is getting a pre-assembled computer, SSG is like ordering a computer that was mass-produced and is sitting ready in a warehouse. It’s built once, perfectly optimized, and then shipped instantly whenever someone asks for it.

What it is:

Static Site Generation means that your entire application’s HTML, CSS, and JavaScript are generated at build time, not on each request. These static files are then deployed to a content delivery network (CDN) and served directly to users.

Why it’s important:

SSG offers the ultimate in performance, security, and scalability for content that doesn’t change frequently. It combines the SEO benefits of SSR with unparalleled speed.

How it functions:

  1. Build Time: When you run your build command (e.g., npm run build), your React application is executed. For each page, the framework (like Next.js) fetches all necessary data (from APIs, databases, markdown files, etc.) and pre-renders the HTML.
  2. Static Files Generated: The build process outputs a set of static HTML, CSS, and JavaScript files for every route.
  3. Deployment to CDN: These static files are deployed to a CDN (Content Delivery Network).
  4. User Request: When a user requests a page, the CDN serves the pre-built HTML file directly.
  5. Instant Content: The browser receives the full HTML instantly, displaying content immediately (near-instant FCP).
  6. JavaScript Hydration: The JavaScript bundles are downloaded and hydrate the page, making it interactive.

Let’s visualize this flow:

flowchart TD A["Developer"] -->|"1. Run Build Command"| B("Build Process") B -->|"2. Fetches Data (APIs/DB/Files)"| C("Data Sources") C -->|"3. Returns Data"| B B -->|"4. React Renders HTML for ALL Pages"| D("Static HTML/JS/CSS Files") D -->|"5. Deploy to CDN"| E("CDN") subgraph Runtime F["User"] -->|"6. Request Page URL"| G("Browser") G -->|"7. Fetches Static Files"| E E -->|"8. Sends Static HTML + JS Bundle"| G G -->|"9. Displays HTML (Instant FCP)"| H("DOM") G -->|"10. React Hydrates DOM"| I("DOM") end

Pros and Cons of SSG:

Pros:

  • Unbeatable Performance: Since files are served directly from a CDN, latency is minimal, leading to incredibly fast page loads (both FCP and LCP).
  • Excellent SEO: All content is present in the initial HTML.
  • High Security: No server-side runtime for dynamic content means fewer attack vectors.
  • Scalability & Reliability: CDNs are designed for massive scale and high availability, handling traffic spikes effortlessly without impacting your origin server.
  • Cost-Effective: Hosting static files is generally cheaper than running dynamic servers.

Cons:

  • Data Staleness: Content is only as fresh as the last build. For highly dynamic content that changes by the second (e.g., a stock ticker), pure SSG is not suitable. However, strategies like Incremental Static Regeneration (ISR) in Next.js mitigate this.
  • Long Build Times: For very large sites with thousands of pages, the build process can take a long time, impacting deployment frequency.
  • Limited Dynamic Content: Pure SSG cannot serve user-specific content without additional client-side logic after hydration.

SSG with Next.js (2026 Context)

Next.js leverages getStaticProps to pre-render pages at build time and getStaticPaths for dynamic routes. It also offers Incremental Static Regeneration (ISR), a powerful feature that allows you to update static pages after they’ve been deployed without needing a full site rebuild. This provides a hybrid approach, offering the benefits of SSG with improved content freshness.

Choosing the Right Strategy: A Decision Guide

The “best” rendering strategy depends entirely on your application’s requirements. There’s no one-size-fits-all answer. Here’s a mental model to help you decide:

  • SPA (CSR):
    • Best for: Highly interactive dashboards, complex admin panels, social media feeds, applications where SEO is not a primary concern, and users are expected to spend a long time within the app after initial load.
    • Think: Gmail, Figma, Trello.
  • SSR:
    • Best for: Content-heavy sites, e-commerce stores, news portals, applications requiring strong SEO and fast initial content display, but with frequent data changes or user-specific content.
    • Think: E-commerce product pages, blog posts, news articles.
  • SSG:
    • Best for: Marketing sites, documentation, blogs, portfolios, e-commerce product listings (where product data doesn’t change by the second), or any content that changes infrequently.
    • Think: Company landing pages, documentation sites, personal blogs.

Hybrid Approaches: Modern frameworks like Next.js allow you to mix and match these strategies within a single application. You might have a marketing landing page rendered with SSG, a dynamic user dashboard with SSR, and a highly interactive form that’s purely client-side rendered after initial load. This is the power of a flexible architecture!


Step-by-Step Implementation: Demonstrating Rendering Differences with Next.js

Let’s get our hands dirty and see how these strategies manifest in a real-world framework. We’ll use Next.js (version 14.x, running on Node.js 20.x) as our example, as it’s the industry standard for hybrid React rendering.

First, ensure you have Node.js (v20.x or newer) and npm/yarn installed.

Project Setup

  1. Create a new Next.js project: Open your terminal and run:

    npx create-next-app@latest rendering-strategies-demo
    

    When prompted:

    • Would you like to use TypeScript? No (for simplicity, but recommended for production)
    • Would you like to use ESLint? Yes
    • Would you like to use Tailwind CSS? No
    • Would you like to use src/ directory? Yes
    • Would you like to use App Router? (recommended) Yes
    • Would you like to customize the default import alias? No
  2. Navigate into your project:

    cd rendering-strategies-demo
    
  3. Run the development server:

    npm run dev
    

    Your app should now be running at http://localhost:3000.

1. Client-Side Rendering (CSR) in Next.js

Even with Next.js, you can implement CSR for parts of your application. This is typically done when you need dynamic, user-specific data that can’t be pre-rendered, or when the initial content is not critical for SEO.

Let’s create a page that fetches data only on the client-side after the initial render.

  1. Create a new page file: Inside src/app, create a new folder client-only and inside it, a file page.jsx.

    src/app/client-only/page.jsx
    
  2. Add the client-side code: Open src/app/client-only/page.jsx and add the following:

    'use client'; // This directive marks the component as a Client Component
    
    import { useState, useEffect } from 'react';
    
    export default function ClientOnlyPage() {
      const [data, setData] = useState(null);
      const [loading, setLoading] = useState(true);
      const [error, setError] = useState(null);
    
      useEffect(() => {
        async function fetchData() {
          try {
            // Simulate a network request
            const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
            if (!response.ok) {
              throw new Error(`HTTP error! status: ${response.status}`);
            }
            const result = await response.json();
            setData(result);
          } catch (e) {
            setError(e);
          } finally {
            setLoading(false);
          }
        }
    
        fetchData();
      }, []); // Empty dependency array means this runs once on mount
    
      if (loading) return <p>Loading client-side data...</p>;
      if (error) return <p>Error: {error.message}</p>;
    
      return (
        <div style={{ padding: '20px', border: '1px solid #ccc', borderRadius: '8px' }}>
          <h1>Client-Side Rendered Page</h1>
          <p>This content is fetched and rendered *after* the initial page load in the browser.</p>
          <h2>Fetched Data:</h2>
          <pre>{JSON.stringify(data, null, 2)}</pre>
        </div>
      );
    }
    

    Explanation:

    • 'use client';: This crucial directive at the top tells Next.js that this module and its children are Client Components. This means they will be rendered on the client (browser) and can use hooks like useState and useEffect. Without this, Next.js would attempt to render it as a Server Component by default.
    • useState and useEffect: These React hooks are used to manage the component’s state (data, loading, error) and perform side effects (data fetching) when the component mounts in the browser.
    • fetch('...'): This standard browser API is used to fetch data. This fetch call only happens after the JavaScript has loaded and executed in the client’s browser.
  3. Visit the page: Open http://localhost:3000/client-only in your browser. You’ll notice a “Loading client-side data…” message briefly before the fetched data appears. If you view the page’s source (Ctrl+U or Cmd+Option+U), you’ll see that the initial HTML sent from the server does not contain the fetched data. It only contains the <h1>Client-Side Rendered Page</h1> and the initial loading state.

2. Server-Side Rendering (SSR) in Next.js

Now, let’s create a page where the data is fetched and rendered on the server before being sent to the browser. Next.js’s App Router handles this elegantly with Server Components and async components.

  1. Create a new page file: Inside src/app, create a new folder server-render and inside it, a file page.jsx.

    src/app/server-render/page.jsx
    
  2. Add the server-side code: Open src/app/server-render/page.jsx and add the following:

    // No 'use client' directive means this is a Server Component by default
    
    async function fetchDataFromServer() {
      // This function runs on the server during the request
      const response = await fetch('https://jsonplaceholder.typicode.com/todos/2', {
        cache: 'no-store' // Ensures data is fresh on every request for SSR
      });
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      return response.json();
    }
    
    export default async function ServerRenderPage() {
      let data = null;
      let error = null;
    
      try {
        data = await fetchDataFromServer();
      } catch (e) {
        error = e.message;
      }
    
      return (
        <div style={{ padding: '20px', background: '#f0f8ff', borderRadius: '8px' }}>
          <h1>Server-Side Rendered Page</h1>
          <p>This content is fetched and rendered *on the server* before being sent to your browser.</p>
          {error ? (
            <p>Error fetching data: {error}</p>
          ) : (
            <>
              <h2>Fetched Data:</h2>
              <pre>{JSON.stringify(data, null, 2)}</pre>
            </>
          )}
        </div>
      );
    }
    

    Explanation:

    • No 'use client': By default, components in the App Router are Server Components. This means they run on the server.
    • async function ServerRenderPage(): Server Components can be async, allowing you to await data fetching directly within the component. This is a powerful feature of modern React and Next.js.
    • fetch('...', { cache: 'no-store' }): The fetch function here runs on the server. The cache: 'no-store' option is important for SSR to ensure that the data is always fresh for each incoming request. If omitted, Next.js might cache the data, turning it into a form of SSG (which we’ll see next).
  3. Visit the page: Open http://localhost:3000/server-render in your browser. You’ll notice that the data is immediately visible. If you view the page’s source, you’ll see the complete HTML, including the fetched data, already present. This is the core benefit of SSR!

3. Static Site Generation (SSG) in Next.js

Finally, let’s create a page that generates its HTML at build time.

  1. Create a new page file: Inside src/app, create a new folder static-generate and inside it, a file page.jsx.

    src/app/static-generate/page.jsx
    
  2. Add the static generation code: Open src/app/static-generate/page.jsx and add the following:

    // This is also a Server Component, but Next.js will detect static generation
    
    async function fetchDataForStaticGeneration() {
      // This function runs at build time
      console.log('Fetching data for static generation...'); // This will only appear in your build logs!
      const response = await fetch('https://jsonplaceholder.typicode.com/todos/3');
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      return response.json();
    }
    
    export default async function StaticGeneratePage() {
      let data = null;
      let error = null;
    
      try {
        data = await fetchDataForStaticGeneration();
      } catch (e) {
        error = e.message;
      }
    
      return (
        <div style={{ padding: '20px', background: '#e0ffe0', borderRadius: '8px' }}>
          <h1>Static Site Generated Page</h1>
          <p>This content is fetched and rendered *at build time*.</p>
          {error ? (
            <p>Error fetching data: {error}</p>
          ) : (
            <>
              <h2>Fetched Data:</h2>
              <pre>{JSON.stringify(data, null, 2)}</pre>
            </>
          )}
        </div>
      );
    }
    

    Explanation:

    • fetch('...'): In Server Components within the App Router, fetch calls are automatically memoized and cached by Next.js by default when no cache option is provided. This means if the data is fetchable at build time, Next.js will automatically perform SSG for this page.
    • The console.log will appear in your terminal when you run npm run build, not when you visit the page in the browser. This confirms it runs at build time.
  3. Run the build process: First, stop your development server (Ctrl+C). Then, run:

    npm run build
    

    You will see output indicating that Next.js is building your pages. Look for logs related to /static-generate.

  4. Start the production server:

    npm run start
    
  5. Visit the page: Open http://localhost:3000/static-generate in your browser. Again, the data is immediately visible. If you view the page source, it will contain the full HTML with the data. The key difference from SSR is when this HTML was generated: at build time, not on each request.


Mini-Challenge: Dynamic SSG with revalidate

You’ve seen how SSG works, but what if your “static” content needs to be updated periodically without a full rebuild? Next.js offers Incremental Static Regeneration (ISR) to bridge this gap.

Challenge: Modify the src/app/static-generate/page.jsx to use ISR, allowing the page to be re-generated in the background every 10 seconds.

Hint: Next.js’s fetch API, when used in a Server Component, supports a revalidate option in its cache object. This is how you implement ISR.

What to Observe/Learn:

  1. How to configure ISR for a page.
  2. The behavior of ISR: The first request after the revalidate interval might serve stale data, but subsequent requests (after a background re-generation) will show updated data.
  3. The benefits of ISR for content freshness without full rebuilds.

Common Pitfalls & Troubleshooting

  1. Hydration Mismatches (SSR/SSG):

    • Pitfall: You might see errors like Warning: Prop 'className' did not match. or Text content did not match.
    • Reason: This happens when the HTML generated on the server (or at build time) doesn’t exactly match the HTML that React tries to render on the client during hydration. Common causes include:
      • Client-side only code (like a useEffect that changes the DOM on mount) running before hydration.
      • Browser extensions injecting HTML.
      • Incorrectly using browser-specific APIs (e.g., window or document) in server components without proper checks.
    • Troubleshooting:
      • Ensure your components render deterministically on both the server and client.
      • If you must use client-specific APIs, wrap them in useEffect with an empty dependency array or use a conditional check (typeof window !== 'undefined').
      • For components that absolutely cannot be server-rendered (e.g., complex charts that rely on canvas), mark them with 'use client' and ensure they only render on the client.
  2. SEO Issues with Pure SPAs:

    • Pitfall: Your content-heavy SPA isn’t ranking well in search results.
    • Reason: While modern search engines are better at crawling JavaScript, they still prefer pre-rendered HTML for reliable indexing.
    • Troubleshooting:
      • For critical content pages, migrate to SSR or SSG.
      • Use tools like Google Search Console’s URL Inspection to see how Googlebot renders your page.
      • Ensure your SPA has proper <title> and <meta> tags updated dynamically.
  3. Long Build Times (SSG):

    • Pitfall: Your npm run build command takes an excessively long time for large sites.
    • Reason: Generating thousands of static pages can be CPU-intensive.
    • Troubleshooting:
      • Implement ISR: For pages that don’t need to be updated with every deploy, use ISR to re-generate them on demand rather than at build time.
      • Optimize Data Fetching: Ensure your fetch calls are efficient and parallelized during the build.
      • Split Builds: For extremely large sites, consider breaking the site into smaller, independently deployable parts (this hints at Microfrontends, which we’ll cover later!).
  4. Server Overload (SSR):

    • Pitfall: Your SSR server becomes slow or crashes under high traffic.
    • Reason: Every request requires your server to execute React and fetch data, which consumes resources.
    • Troubleshooting:
      • Caching: Implement server-side caching for frequently accessed data or entire page fragments.
      • Optimize Data Fetching: Ensure your server-side data fetching is as fast as possible.
      • Scale Your Server: Increase server resources or use a serverless platform that scales automatically (e.g., Vercel, AWS Lambda).
      • Consider SSG/ISR: If content doesn’t need to be real-time, switch to SSG or ISR for those pages.

Summary

Phew! We’ve covered a lot of ground in this chapter, diving deep into the world of web rendering strategies. Here are the key takeaways:

  • Client-Side Rendering (CSR) / SPAs load an empty HTML shell and render content dynamically in the browser. Great for rich, interactive apps, but can suffer from slow initial load and SEO challenges.
  • Server-Side Rendering (SSR) generates full HTML on the server for each request, sending it to the browser. This provides fast initial content (FCP) and excellent SEO, but increases server load.
  • Static Site Generation (SSG) pre-renders HTML for all pages at build time, deploying static files to a CDN. It offers unparalleled performance, security, and scalability, ideal for static or infrequently changing content.
  • Next.js (v14.x+) is a powerful React framework that enables all these strategies, often in a hybrid fashion, leveraging React 18’s Server Components and fetch caching for intelligent rendering decisions.
  • Choosing the right strategy involves understanding your application’s requirements for initial load speed, SEO, data freshness, and interactivity. Modern applications often combine these approaches.
  • Be mindful of common pitfalls like hydration mismatches, SEO for SPAs, build times for SSG, and server load for SSR.

Understanding these rendering strategies is fundamental to designing scalable, performant, and user-friendly React applications. As you progress, you’ll find yourself constantly evaluating these trade-offs.

What’s Next? In Chapter 5, we’ll build upon this foundation by exploring advanced rendering techniques that push the boundaries of performance and user experience. Get ready to dive into Streaming SSR, React Server Components, Islands Architecture, and Edge Rendering – the cutting edge of modern frontend architecture!


References

  1. React Official Documentation: https://react.dev/
  2. Next.js Official Documentation: https://nextjs.org/docs
  3. MDN Web Docs - Introduction to client-side frameworks: https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Frameworks_libraries/Introduction
  4. MDN Web Docs - Getting started with React: https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Frameworks_libraries/React_getting_started
  5. acdlite/react-fiber-architecture - React’s Design Principles: https://github.com/acdlite/react-fiber-architecture
  6. Rendering Strategies in Modern Web Development - DEV Community: https://dev.to/austinwdigital/rendering-strategies-in-modern-web-development-2lpe
  7. Server-Side Rendering (SSR) vs. Client-Side: The 2026 Verdict: https://www.jasminedirectory.com/blog/server-side-rendering-ssr-vs-client-side-the-2026-verdict/

This page is AI-assisted and reviewed. It references official documentation and recognized resources where relevant.