All Systems Operational
Powered By
profound-logo
profound-logoProfound CMS
⌘K
Admin

Rendu statique avec prise en charge du mode édition

explique comment le site de documentation obtient des chargements de pages statiques rapides tout en conservant la fonctionnalité du mode édition du CMS

Continue Reading
Previous‹Configurer Proxy Panneau AdminNextScripts dans le générateur de modèles›

Hybride

Renderer ProjetRoutage paramétriqueTypes de composantsSseConfigurer Proxy Panneau AdminRendu statique avec prise en charge du mode éditionScripts dans le générateur de modèlesCreate Profound Next

Sans tête

Démarrage rapideJson Et Claude CodeRécupération du schéma Zod du composant

Mcp

Mcp

fonctionnalités du CMS

Feat Docs TemplateGénérateur de modèles de fonctionnalitéFonctionnalité TraducteurFonctionnalité Organisation

Motivation

Notre approche

Terminologie

Hybride Vs Sans Interface

Ce guide explique comment le site de documentation obtient des chargements de pages statiques rapides tout en conservant la fonctionnalité du mode édition du CMS.

Architecture à double route

Nous utilisons deux routes pour le même contenu :

app/
├── [...slug]/page.tsx          # Production : force-static (rapide)
└── preview/[...slug]/page.tsx  # Mode édition : force-dynamic (lit searchParams)

Un middleware proxy réécrit de manière transparente les requêtes en mode édition :

Requête de l'utilisateur : /en/headless/quickstart?edit_mode=true
       ↓
Le proxy détecte ?edit_mode=true
       ↓
Réécriture interne vers : /preview/en/headless/quickstart?edit_mode=true
       ↓
La route dynamique rend avec des wrappers d'édition

L'utilisateur ne voit jamais /preview dans son URL - c'est une réécriture interne.

Fonctionnement

Chemin de production (par défaut)

// app/[...slug]/page.tsx
export const dynamic = 'force-static';
export const revalidate = 60;

export default async function Page({ params }) {
  // Pas de searchParams - la page est entièrement statique
  
  • Les pages sont pré-rendues au moment du build
  • Servies instantanément depuis le cache en périphérie du CDN
  • Revalidées toutes les 60 secondes (ISR) comme filet de sécurité

Chemin du mode édition

// app/preview/[...slug]/page.tsx
export const dynamic = 'force-dynamic';

export default async function PreviewPage({ params, searchParams }) {
  // searchParams disponibles - peut détecter edit_mode
  return <ParametricRoutePage params={params
  • Rendue à chaque requête
  • Peut lire ?edit_mode=true depuis l'URL
  • Rend avec les wrappers éditables du CMS et les contours des blocs

La réécriture par le proxy

// src/proxy.ts
export const proxy = async (request: NextRequest) => {
  const { pathname, searchParams } = request.nextUrl;

  const editMode = searchParams.get('edit_mode');

Comparaison des performances

ScénarioTemps de réponseRendu
Page de production (en cache)~50-100 msStatique depuis le CDN
Page de production (périmée)~50-100 ms + actualisation en arrière-planStatique, puis ISR
Mode édition~500-1500 msSSR dynamique

Comprendre l'ISR (Incremental Static Regeneration)

Le paramètre revalidate = 60 active l'ISR. Cela ne signifie PAS que les pages sont recalculées toutes les 60 secondes.

L'ISR utilise un modèle stale-while-revalidate :

Une requête arrive :
  → La page en cache a-t-elle moins de 60 s ? → Servir depuis le cache (instantané)
  → La page en cache a-t-elle plus de 60 s ? → Servir le cache périmé (instantané)
                                + revalider en arrière-plan pour la requête suivante

Pas de requêtes = Pas de recalcul. Jamais.

Exemple :

  • Page mise en cache à 10 h 00
  • Aucun visiteur jusqu'à 15 h 00
  • Le premier visiteur à 15 h 00 reçoit immédiatement le cache périmé
  • Une actualisation en arrière-plan se produit, le visiteur suivant obtient un contenu à jour

La fenêtre de 60 secondes est un filet de sécurité. Idéalement, nous utiliserions une revalidation à la demande via des webhooks lorsque le contenu du CMS change.

Quand utiliser chaque route

Cas d'utilisationURLRoute utilisée
Navigation normale/en/headless/quickstartStatique
Constructeur de modèles du CMS/en/headless/quickstart?edit_mode=truePreview (via réécriture)
Prévisualisation de bloc IA/en/headless/quickstart?ai_preview=1Preview (via réécriture)

Pourquoi ne pas simplement utiliser le rendu dynamique ?

L'approche simple (pas de force-static, pas de route de prévisualisation) fonctionne mais est lente :

// Approche simple - fonctionne mais ~1-2 s par requête
export default async function Page({ params, searchParams }) {
  return <ParametricRoutePage params={params} searchParams={searchParams} />;
}

Cela effectue un rendu dynamique à chaque requête. Pour un site de documentation avec de nombreuses pages, cela signifie :

  • Des démarrages à froid sur chaque page
  • Aucun bénéfice du cache en périphérie du CDN
  • Des temps de chargement de 1 à 2 secondes contre des millisecondes

L'architecture à double route nous offre le meilleur des deux mondes : la vitesse statique pour les lecteurs, la fonctionnalité dynamique pour les éditeurs.

return
<
ParametricRoutePage
params
={
params
} />;
}
}
searchParams
={
searchParams
} />;
}
const
aiPreview
=
searchParams.
get
(
'ai_preview'
);
// Réécrire vers la route preview si edit_mode ou ai_preview est présent
if ((editMode === 'true' || editMode === '1' || aiPreview) && !pathname.startsWith('/preview')) {
const url = request.nextUrl.clone();
url.pathname = `/preview${pathname}`;
return NextResponse.rewrite(url);
}
return NextResponse.next();
};