Static Site Generation vs Server-side Rendering vs Client-side Rendering
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
useEffectbecause 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
- 32-bit vs 64-bit
- AES vs RSA
- Agent vs Agentless
- Annotations vs Decorators
- Terraform vs Ansible
- BASH vs ZSH
- BigQuery vs Bigtable
- Block Storage vs File Storage vs Object Storage
- Canvas vs SVG
- cgroupfs vs systemd
- Constructor vs Init() vs Factory
- Container Image vs Helm Chart vs OCI Bundle
- Containers vs Virtual Machines (VMs)
- C vs C++
- Java vs C++
- Rust vs C++
- crictl vs ctr
- Dagger vs Guice
- DMA vs RDMA
- DOM vs Virtual DOM vs Shadow DOM
- DQL vs DDL vs DCL vs DML
- eBPF vs Sidecar
- Flux vs Redux
- Full Disk Encryption vs Partition Encryption
- Gatekeeper vs OPA
- Google vs Open Source
- Why MCP uses JSON-RPC 2.0 instead of grpc
- gRPC vs OpenAPI
- gtag.js vs Google Tag Manager (GTM)
- Versus
- Kotlin vs Java
- Jetty vs Netty
- .js vs .jsx vs .ts vs .tsx
- Kata Containers vs KubeVirt
- Linux Namespace vs Kubernetes Namespace
- Linux vs BSD
- LLVM vs JVM
- Data Mining vs Machine Learning vs Artificial Intelligence vs Data Science
- Managed Kubernetes vs Self-managed Kubernetes
- Management Plane vs Control Plane vs Data Plane
- Microcontroller vs Microprocessor vs Computer
- MMU vs IOMMU
- Single-tenant vs Multi-tenant vs Multi-single-tenant
- Multithreading vs Multiprocessing vs Distributed Systems
- Node.js vs Erlang
- OCI Image vs Docker Image
- OCI vs CRI
- OpenSSH vs OpenSSL
- Pass-by-value vs Pass-by-reference
- Podman vs nerdctl
- POSIX vs SUS vs LSB
- Private Key vs Public Key vs Certificate
- Proto Edition 2024 vs Proto Edition 2023
- Proto2 vs Proto3 vs Proto Editions
- Message Queue vs PubSub
- React vs Flutter vs Angular
- REST vs SOAP
- RSA vs ECDSA
- select vs. poll vs. epoll
- SLI vs SLO vs SLA
- Spanner vs Bigtable
- Static Site Generation vs Server-side Rendering vs Client-side Rendering
- Stack based VM vs Register based VM
- Stateless vs Stateful
- Strong Consistency vs Eventual Consistency
- stubs vs mocks vs fakes
- Subroutines vs Coroutines vs Generators
- Software Engineer vs Site Reliability Engineer
- Symlinks vs Hard Links
- JAX vs Tensorflow
- Tensorflow vs PyTorch
- Terminal vs Shell
- Throttling vs Load Shedding
- Unix Domain Sockets vs Network Sockets
- Unix Domain Sockets vs Shared Memory
- URI vs URN vs URL vs URC
- Valkey vs Redis vs Memcached
- Vi vs Vim vs gVim vs Neovim
- WAL vs rollback journal

