logo

Static Site Generation vs Server-side Rendering vs Client-side Rendering

Last Updated: 2023-10-21

TL;DR

What does "rendering" mean?

Rendering = generating HTML

3 primary rendering modes

A rendering mode defines the stage at which your page’s user-facing HTML is generated.

  • Static Site Generation (SSG): render at build time.
  • Server-side Rendering (SSR): render at run time, on server-side.
  • Client-side Rendering (CSR): render at run time, on client-side (browsers).

Many popular frameworks (e.g. Next.js, Gasby.js) now support multiple rendering options.

Client-side Rendering (CSR)

Render on client-side (browser) at run time; all logic, data fetching, templating and routing are handled on the client rather than the server.

Server sends this empty HTML to the client, and everyting is included in the bundle.js:

<!doctype html>
<html>
  <body>
    <div id="root"></div>
    <script src="/static/js/bundle.js"></script>
  </body>
</html>

Pros:

  • May update part of the content without full page re-render.
  • May be easier and cheaper to host.

Cons:

  • The amount of JavaScript required tends to grow as an application grows.
  • Could be slow to start.
  • Bad for SEO.

When to use:

  • Single Page App.
  • If your application is only available to authenticated users.

Server-side Rendering (SSR)

Instead of sending an empty HTML file, the server generates the actual HTML, and send it to the client. The HTML file may still include the <script> tag, which runs React on the client to handle any interactivity. Instead of conjuring all of the DOM nodes from scratch, it instead adopts the existing HTML (i.e. the process of "hydration", watering the "dry" HTML with the "water" of interactivity and event handlers).

The initial render happens in a server runtime like Node.js, using the ReactDOMServer APIs.

CSR and SSR only differ in rendering the shell; both csr and ssr still send data requests from clients, then render the data.

Pros:

  • Can handle dynamic routes on the fly.
  • Rendered page will always be up-to-date.
  • Avoids additional round-trips for data fetching and templating on the client.
  • Avoid sending lots of JavaScript to the client, which helps achieve a fast Time to Interactive (TTI).
  • Users don't have to stare at an empty white page while the JS bundles are downloaded and parsed.

Cons:

  • Generating pages on the server takes time, which can often result in a slower Time to First Byte (TTFB).

When to use:

  • For pages / sections with user-specific (personalized), authentication-gated information, like profile pages or personalized dashboards.
  • For user-generated content, like comments, that a user would expect to be live immediately after posting.

React Server Components

Components that run exclusively on the server, which has access to Node.js api and can fetch data from databases.

Server Components never re-render. They run once on the server to generate the UI. The rendered value is sent to the client and locked in place. As far as React is concerned, this output is immutable, and will never change.

  • cannot useState, because state can change, but Server Components can't re-render.
  • cannot useEffect because effects only run after the render, on the client, and Server Components never make it to the client.

Traditional components (Client Components) render on both the client and the server.

All components are assumed to be Server Components by default. Add 'use client' for client components.

Static Site Generation (SSG)

A variant of Server Side Rendering. The entire site is pre-rendered into HTML, CSS, and JavaScript at build time, which then get served as static assets to the browser. The content is ready to go before the visitor even visits the site.

Pros:

  • No running servers or databases.
    • Can be easily deployed to cloud storages (AWS S3, GCP Cloud Storage, etc).
    • Content gets to the user faster.
    • Secure, no binaries to be hacked.
  • Can be cached by the CDN.
  • Good for SEO: the content can be crawled even for crawlers that don’t execute JavaScript code.

Cons:

  • Individual HTML files must be generated for every possible URL.
    • Cannot handle dynamic routes; infeasible if you don’t know all the URLs at the build time
    • Long time to build and deploy if your site has a large number of unique pages.

When to use:

  • For web pages that don’t change depending on the user: home pages, landing pages, technical documentation, blog, etc.

Mixed Options

Deferred Static Generation (DSG)

An option in between SSG and SSR: statically generate critical pages at build time, and defer non-critical page generation until a user requests it.

Pros: reduce build and deploy time, while keeping the critical pages readily available.

Use case: larger sites that have lots of infrequently accessed content, like old blog posts.

Static Rendering vs Prerendering

  • Static Rendering: pages are interactive without the need to execute much client-side JS
  • Prerendering: improves the First Paint or First Contentful Paint of a Single Page Application that must be booted on the client in order for pages to be truly interactive.

To test:

  • disable JavaScript and load the created web pages. For statically rendered pages, most of the functionality will still exist without JavaScript enabled. For prerendered pages, there may still be some basic functionality like links, but most of the page will be inert.
  • slow your network down using Chrome DevTools, and observe how much JavaScript has been downloaded before a page becomes interactive. Prerendering generally requires more JavaScript to get interactive, and that JavaScript tends to be more complex than the Progressive Enhancement approach used by static rendering.

Rehydration

Combining SSR and CSR via rehydration.

Rehydration = client-side JavaScript converts a static HTML web page, delivered either through static hosting or server-side rendering, into a dynamic web page by attaching event handlers to the HTML elements.

This allows for a fast "first contentful paint" (when useful data is first displayed to the user), but there is a period of time afterward where the page appears to be fully loaded and interactive, but is not until the client-side JavaScript is executed and event handlers have been attached.

Reference