Dwarves
Memo
Type ESC to close search bar

Rendering strategies in React

Client-side rendering (CSR), server-side rendering (SSR), and static-site generation (SSG) are three key rendering strategies in modern web development. Each approach has unique advantages and trade-offs, impacting application performance, SEO, and user experience.

Client-side rendering (CSR)

CSR is the default rendering approach in React applications, where everything from data fetching to rendering happens in the browser. The server delivers a minimal HTML file with a JavaScript bundle, and React takes over from there, rendering the content on the client’s side.

How it works

Advantages

Disadvantages

Example in React

In CSR, data fetching happens on the client side, typically using hooks like useEffect.

import { useState, useEffect } from 'react'

function UserProfile({ userId }) {
  const [user, setUser] = useState(null)

  useEffect(() => {
    fetch(`/api/users/${userId}`)
      .then((response) => response.json())
      .then((data) => setUser(data))
  }, [userId])

  return user ? <div>{user.name}</div> : <div>Loading...</div>
}

Server-side rendering (SSR)

SSR generates HTML on the server for each request. When the user requests a page, the server processes the JavaScript, fetches any necessary data, and returns a fully-rendered HTML page. React components are rendered to HTML strings on the server and sent to the client, where React “hydrates” (attaches event listeners) to the HTML.

How it works

Advantages

Disadvantages

Example in Next.js

Next.js is a React framework that simplifies SSR. With Next.js, you can use getServerSideProps to fetch data and render it on the server.

// pages/profile/[id].js

import React from 'react'

export async function getServerSideProps(context) {
  const { id } = context.params
  const res = await fetch(`https://api.example.com/users/${id}`)
  const user = await res.json()

  return { props: { user } }
}

export default function UserProfile({ user }) {
  return <div>{user.name}</div>
}

Static-site generation (SSG)

SSG generates HTML at build time. Unlike SSR, which renders HTML on each request, SSG pre-renders pages as static files and serves them on request. This is ideal for content that doesn’t change frequently, as it combines the benefits of SSR with the speed of serving static files.

How it works

Advantages

Disadvantages

Example in Next.js

In Next.js, getStaticProps generates static pages at build time. This is perfect for content like blog posts or product pages.

// pages/posts/[id].js

import React from 'react'

export async function getStaticProps({ params }) {
  const res = await fetch(`https://api.example.com/posts/${params.id}`)
  const post = await res.json()

  return { props: { post } }
}

export async function getStaticPaths() {
  const res = await fetch('https://api.example.com/posts')
  const posts = await res.json()

  const paths = posts.map((post) => ({
    params: { id: post.id.toString() },
  }))

  return { paths, fallback: false }
}

export default function Post({ post }) {
  return <div>{post.title}</div>
}

Comparing CSR, SSR, and SSG

FeatureCSR (client-side rendering)SSR (server-side rendering)SSG (static-site generation)
Data fetchingClient-side (after page load)Server-side (on each request)Server-side (at build time)
RenderingBrowserServer for initial, browser for subsequent interactionsServer at build time, browser for interactions
Best forHighly interactive apps, SPAsSEO-sensitive, frequently updated contentStatic content, rarely changing pages
SEOLimited SEO (due to initial blank HTML)Great SEO (initial HTML contains full content)Great SEO (pre-rendered HTML at build time)
Initial load timeDepends on bundle size, slower initial loadFaster initial load, HTML is pre-renderedFastest (serving static files), low latency
Content freshnessReal-time updatesReal-time updatesStale until next build
Hosting costLower hosting cost (only needs a static server)Higher hosting cost (server processes each request)Lower hosting cost (can use CDN for static files)

Choosing between CSR, SSR, and SSG

Combining CSR, SSR, and SSG

In some cases, applications use a hybrid approach to leverage the strengths of each technique. For instance:

Example hybrid approach in Next.js

In this example, we use SSG with ISR for product pages and CSR for interactive features like adding items to a cart.

// pages/product/[id].js

import { useState } from 'react'

export async function getStaticProps({ params }) {
  const res = await fetch(`https://api.example.com/products/${params.id}`)
  const product = await res.json()

  return { props: { product }, revalidate: 60 } // ISR: regenerates every 60 seconds
}

export async function getStaticPaths() {
  const res = await fetch('https://api.example.com/products')
  const products = await res.json()

  const paths = products.map((product) => ({
    params: { id: product.id.toString() },
  }))

  return { paths, fallback: 'blocking' }
}

export default function Product({ product }) {
  const [cart, setCart] = useState([])

  const addToCart = () => {
    setCart((prevCart) => [...prevCart, product])
  }

  return (
    <div>
      <h1>{product.name}</h1>
      <button onClick={addToCart}>Add to Cart</button>
    </div>
  )
}

Summary

Choosing between CSR, SSR, and SSG depends on your application’s needs for SEO, content freshness, interactivity, and performance. In many modern apps, a hybrid approach allows you to take advantage of each strategy where it’s most beneficial, creating a fast, SEO-friendly, and interactive experience. Leveraging frameworks like Next.js simplifies managing these different rendering methods in a single React application, making it easier to build performant, user-friendly applications.