DEV Community

Muhammad Hamza
Muhammad Hamza

Posted on • Edited on

Mastering SSR & CSR in Next.js with GraphQL – With and Without Apollo

When working with Next.js (13+) and GraphQL, choosing between Server-Side Rendering (SSR) and Client-Side Rendering (CSR) has a major impact on performance, SEO, and user experience.

So, what’s the right approach when fetching GraphQL data from a NestJS backend? Let’s break it down!

1️⃣ SSR vs. CSR – Key Differences in Next.js 13+

SSR (Server-Side Rendering)

  • Data is fetched on the server before rendering.
  • Ideal for SEO-heavy pages (e.g., blogs, product pages).
  • Implemented using Server Components or fetch() inside async functions in React Server Components.

CSR (Client-Side Rendering)

  • The page loads first, then fetches data on the client.
  • Suitable for dynamic dashboards and interactive UIs.
  • Implemented using useEffect() with fetch() or Apollo Client.

2️⃣ Using GraphQL in Next.js 13+ – Apollo vs. Fetch?

🔹 With Apollo Client (CSR & Hybrid SSR/CSR)

  • Ideal for apps needing real-time updates & caching.
  • Works well in Client Components, but requires extra setup for SSR.
  • Use @apollo/client with useQuery() in Client Components.

🔹 Without Apollo (Using fetch/GraphQL-request)

  • Simpler and better for SSR.
  • Use fetch() inside Server Components to get GraphQL data directly.
  • Reduces bundle size and avoids unnecessary dependencies.

3️⃣ How to Implement GraphQL Fetching in Next.js 13+?

✔️ For SSR (Recommended for SEO & Fast Performance)


// Using Server Component (App Router)
async function BlogPost({ params }: { params: { id: string } }) {
  const res = await fetch("https://api.example.com/graphql", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ query: `{ post(id: "${params.id}") { title, content } }` }),
    cache: "no-store", // Avoids caching for fresh data
  });

  const { data } = await res.json();
  return <h1>{data.post.title}</h1>;
}

export default BlogPost;
Enter fullscreen mode Exit fullscreen mode

✔️ For CSR (Recommended for Interactive Dashboards)

"use client";
import { useQuery, gql } from "@apollo/client";

const GET_POST = gql`
  query GetPost($id: ID!) {
    post(id: $id) {
      title
      content
    }
  }
`;

function BlogPost({ id }: { id: string }) {
  const { data, loading, error } = useQuery(GET_POST, { variables: { id } });

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error fetching post</p>;

  return <h1>{data.post.title}</h1>;
}

export default BlogPost;
Enter fullscreen mode Exit fullscreen mode

4️⃣ When to Use What?

✔️ SEO-Focused Pages? → Use SSR (Server Components + fetch()).

✔️ Highly Interactive Dashboards? → Use CSR (Apollo Client + useQuery).

✔️ Hybrid Approach? → Preload critical data with SSR, hydrate client-side with Apollo.

🔹 Pro Tip: For frequently changing data, ISR (Incremental Static Regeneration) helps balance performance & freshness.

💡 Final Thoughts

GraphQL + Next.js (13+) is powerful, but choosing the right rendering strategy is crucial.

👉 What’s your go-to approach for using GraphQL in Next.js 13+? Let’s discuss in the comments! 🚀

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay