Comparison (Mis à jour: 02/06/2026)

SSR vs SSG avec Claude Code: choisir le rendu Next.js et Astro

Comparez SSR, SSG, ISR et export statique dans Next.js/Astro avec Claude Code, exemples exécutables et vérification.

SSR vs SSG avec Claude Code: choisir le rendu Next.js et Astro

Clarifier les termes

Choisir entre SSR et SSG ne revient pas seulement à choisir ce qui paraît le plus rapide. SSR signifie server-side rendering: le serveur fabrique le HTML quand une requête arrive. SSG signifie static site generation: le HTML est généré pendant le build, puis servi par un CDN ou un hébergeur statique. ISR, Incremental Static Regeneration, est l’option intermédiaire: servir une page statique, puis la régénérer après une durée ou un événement.

Le piège fréquent avec Next.js App Router est de croire qu’un Server Component implique forcément du SSR à chaque requête. Ce n’est pas le cas. Dans la documentation actuelle des Dynamic Route Segments, les exemples TypeScript typent params comme une Promise. Si vous voulez signaler explicitement qu’un rendu doit attendre une vraie requête, l’API actuelle est connection.

Si vous demandez seulement à Claude Code de rendre une page plus rapide, il peut trop statifier et figer stock, recherche ou interface membre. Si vous demandez du SSR partout, vous risquez d’augmenter le TTFB et le coût serveur. La bonne première étape est une matrice de routes: fraîcheur des données, personnalisation, fréquence de mise à jour, impact monétisation et commande de vérification.

Comparaison et cas concrets

QuestionSSGISRSSR
Moment de génération HTMLBuildBuild et revalidationRequête
Pages adaptéesArticles, docs, landing pagesProduits, catégories, actualitésTableaux de bord, recherche, panier
FraîcheurSnapshot du buildTemps ou événementPresque actuel
CoûtFaibleMoyenSouvent plus élevé
Risque courantBuilds longs, contenu ancienAncienne réponse visible brièvementLent sans cache

Premier cas: un blog ou une documentation. Si le contenu, l’OGP, les liens internes et le CTA sont fixes au moment de publier, SSG est le choix le plus simple. Vous reconstruisez quand l’article change. Pour réduire aussi le JavaScript, lisez code splitting avec Claude Code.

Deuxième cas: une page produit. Prix, disponibilité et classement des catégories peuvent changer toutes les quelques minutes, mais les visiteurs doivent recevoir une réponse rapide. ISR convient bien. Le guide officiel Next.js ISR précise notamment qu’ISR fonctionne avec le runtime Node.js et pas avec static export.

Troisième cas: un tableau de bord membre. Cookies, droits, facturation, notifications et recommandations privées dépendent de la requête. Traitez-le comme SSR et fixez des en-têtes de cache clairs. Si votre équipe envisage l’edge pour certaines routes dynamiques, consultez edge computing avec Claude Code après avoir décidé quelles données peuvent s’en approcher.

Exemple SSR avec Next.js

Cet exemple peut être copié dans un projet Next.js App Router. Il utilise dummyjson.com, donc aucune clé API n’est nécessaire. connection() et cache: "no-store" rendent le comportement à la requête explicite pendant la revue.

// app/products/[id]/page.tsx
import { notFound } from "next/navigation";
import { connection } from "next/server";

type Product = {
  id: number;
  title: string;
  price: number;
  stock: number;
  updatedAt: string;
};

async function getProduct(id: string): Promise<Product | null> {
  await connection();

  const res = await fetch(`https://dummyjson.com/products/${id}`, {
    cache: "no-store",
  });

  if (res.status === 404) return null;
  if (!res.ok) throw new Error(`Failed to load product: ${res.status}`);

  const data = (await res.json()) as {
    id: number;
    title: string;
    price: number;
    stock: number;
    meta?: { updatedAt?: string };
  };

  return {
    id: data.id,
    title: data.title,
    price: data.price,
    stock: data.stock,
    updatedAt: data.meta?.updatedAt ?? new Date().toISOString(),
  };
}

export default async function ProductPage({
  params,
}: {
  params: Promise<{ id: string }>;
}) {
  const { id } = await params;
  const product = await getProduct(id);

  if (!product) notFound();

  return (
    <main>
      <h1>{product.title}</h1>
      <p>Price: ${product.price.toLocaleString("en-US")}</p>
      <p>Stock: {product.stock}</p>
      <p>Updated: {new Date(product.updatedAt).toLocaleString("fr-FR")}</p>
    </main>
  );
}

Le principal piège consiste à placer cookies() ou headers() dans un layout partagé parce que c’est pratique. Ces API dépendent de la requête et peuvent rendre dynamiques des routes qui étaient statiques. Si ce layout enveloppe les articles, vous perdez une partie du bénéfice SSG. Demandez à Claude Code de lister les routes affectées avant d’accepter le patch.

SSG, ISR et export statique

SSG et ISR peuvent sembler identiques pour le visiteur, mais leur exploitation diffère. SSG se met à jour au build. ISR se met à jour après une durée ou un événement. L’export statique utilise output: "export" pour produire un dossier out servable sans serveur Node.js. Le guide officiel Static Exports explique que next build peut créer un fichier HTML par route pour l’hébergement statique.

// app/catalog/[id]/page.tsx
import { notFound } from "next/navigation";

export const revalidate = 3600;

type Product = {
  id: number;
  title: string;
  description: string;
};

export async function generateStaticParams() {
  return ["1", "2", "3"].map((id) => ({ id }));
}

async function getProduct(id: string): Promise<Product | null> {
  const res = await fetch(`https://dummyjson.com/products/${id}`, {
    next: { revalidate: 3600, tags: [`product:${id}`] },
  });

  if (res.status === 404) return null;
  if (!res.ok) throw new Error(`Failed to load product: ${res.status}`);

  return (await res.json()) as Product;
}

export default async function CatalogPage({
  params,
}: {
  params: Promise<{ id: string }>;
}) {
  const { id } = await params;
  const product = await getProduct(id);

  if (!product) notFound();

  return (
    <article>
      <h1>{product.title}</h1>
      <p>{product.description}</p>
    </article>
  );
}
// next.config.mjs
const nextConfig = {
  output: "export",
  images: {
    unoptimized: true,
  },
};

export default nextConfig;
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "export:check": "next build && npx serve out"
  }
}

Ne mélangez pas export statique et ISR comme s’ils étaient équivalents. L’export statique est conçu pour un hébergement statique. Si la route a besoin de cookies, de revalidation à la demande, de Server Functions ou de vrai SSR, prévoyez un runtime serveur. Avant que Claude Code n’écrive le code, indiquez la cible: Cloudflare Pages statique, conteneur Node, Vercel, Netlify ou autre.

Astro statique et rendu à la demande

Astro part d’une génération statique par défaut. La documentation officielle Astro on-demand rendering indique que les pages, routes et endpoints sont prérendus au build par défaut. Après ajout d’un adapter serveur, une route peut utiliser export const prerender = false pour être rendue à la demande.

---
// src/pages/docs/[slug].astro
export async function getStaticPaths() {
  const docs = [
    { slug: "ssr", title: "SSR guide" },
    { slug: "ssg", title: "SSG guide" },
  ];

  return docs.map((doc) => ({
    params: { slug: doc.slug },
    props: { doc },
  }));
}

const { doc } = Astro.props;
---

<html lang="fr">
  <body>
    <article>
      <h1>{doc.title}</h1>
      <p>This page was generated at build time.</p>
    </article>
  </body>
</html>
---
// src/pages/account.astro
export const prerender = false;

const session = Astro.cookies.get("session")?.value;
const name = session ? "Masa" : "Guest";

Astro.response.headers.set("Cache-Control", "private, no-store");
---

<html lang="fr">
  <body>
    <h1>Account</h1>
    <p>Hello, {name}.</p>
  </body>
</html>

Le piège Astro est l’oubli de l’adapter. Une page peut sembler correcte en local, mais le rendu à la demande exige un runtime serveur en production. Demandez à Claude Code de vérifier astro.config.mjs, la plateforme de déploiement et chaque surcharge prerender.

Commandes de vérification et prompt

La stratégie de rendu ne se valide pas seulement à la lecture du code. Vérifiez le résultat du build, les en-têtes, les logs de cache et les métriques comme TTFB et LCP. Pour ISR, la documentation Next.js recommande de tester le comportement production avec next build puis next start.

# Next.js: production behavior
npm run build
npm run start

# In another terminal
curl -I http://localhost:3000/catalog/1
curl -I http://localhost:3000/products/1

# ISR cache debugging
NEXT_PRIVATE_DEBUG_CACHE=1 npm run start

# Astro
npm run build
npm run preview

Le prompt doit demander une décision vérifiable, pas seulement du code:

Goal: classify every route in a Next.js/Astro site as SSR, SSG, ISR, or static export.

Inspect:
- app/ or src/pages/ routes
- cookies(), headers(), searchParams, connection(), cache: "no-store"
- generateStaticParams(), revalidate, output: "export", Astro prerender
- monetization pages, member pages, articles, product pages, and search pages

Constraints:
- Do not break SEO metadata or internal links
- Keep npm run build passing before and after
- Return a table with the chosen strategy, reason, touched files, and verification command

Pièges concrets

Premier piège: intégrer du contenu propre à l’utilisateur dans un article statique. Noms de membres, recommandations privées et prix masqués ne doivent pas être figés dans du HTML SSG. Gardez l’article statique et déplacez la personnalisation vers un composant client ou une section explicitement dynamique.

Deuxième piège: choisir un intervalle ISR trop court. revalidate = 1 ramène souvent la charge côté serveur. Si vous avez besoin de précision, utilisez une revalidation à la demande. Si les données doivent être temps réel, utilisez SSR.

Troisième piège: choisir l’export statique puis ajouter des fonctions serveur. Authentification, UI basée sur les cookies, Route Handlers serveur et ISR demandent un runtime. L’hébergement statique est excellent, mais il ne remplace pas un serveur.

Quatrième piège: accepter la proposition de Claude Code simplement parce qu’elle paraît rapide. Pour un site monétisé, la performance n’est qu’une partie de la qualité. OGP, données structurées, liens internes, publicités, tracking CTA, LCP et CLS comptent aussi. Après la décision, utilisez optimisation de performance avec Claude Code.

Recommandation orientée monétisation

Pour une activité de contenu comme ClaudeCodeLab, utilisez SSG par défaut pour les articles, tutoriels, comparatifs et pages d’entrée. Utilisez ISR pour catalogues, catégories et contenus qui tolèrent une courte période d’ancienneté. Utilisez SSR pour comptes, recherche, panier, contexte de paiement et toute route avec données privées de requête.

Pour commencer, prenez la fiche gratuite Claude Code. Pour des modèles et packs d’implémentation, consultez la page produits. Si votre équipe doit cadrer stratégie de routes, permissions, revue de code, analytics et formation de déploiement, commencez par formation et conseil Claude Code.

Ce que j’ai vérifié

Pour cette mise à jour, j’ai vérifié les pages officielles Next.js Dynamic Route Segments, connection, ISR, Static Exports, Astro on-demand rendering et Claude Code overview. Dans le flux de contenu de Masa, la séparation la plus stable a été SSG pour les articles, ISR pour produits et catégories, SSR pour compte et recherche. L’étape Claude Code la plus utile a été la matrice de routes avant les changements de code. Elle a détecté tôt l’usage accidentel de cookies dans des pages statiques et a rendu la revue plus claire grâce à une raison et une commande de vérification par route.

#Claude Code #SSR #SSG #Next.js #Astro #performance
Gratuit

PDF gratuit: cheatsheet Claude Code

Saisissez votre email et téléchargez une page avec commandes, habitudes de review et workflow sûr.

Nous protégeons vos données et n'envoyons pas de spam.

Masa

À propos de l'auteur

Masa

Ingénieur spécialisé dans les workflows pratiques avec Claude Code.