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

Renderização estática com suporte ao modo de edição

explica como o site da documentação obtém carregamentos rápidos de páginas estáticas enquanto mantém a funcionalidade do modo de edição do CMS

Continue Reading
Previous‹Configurar Proxy Do Painel AdministrativoNextScripting no Construtor de Templates›

Híbrido

Projeto RenderizadorRoteamento ParamétricoTipos De ComponentesSseConfigurar Proxy Do Painel AdministrativoRenderização estática com suporte ao modo de ediçãoScripting no Construtor de TemplatesCreate Profound Next

Sem interface

Início rápidoJson E Claude CodeComponente Zod Puxar

Mcp

Mcp

Recursos Do Cms

Recurso Modelo De DocumentosRecurso Construtor De ModelosTradutor De FuncionalidadesRecurso Organizacao

Motivação

Nossa Abordagem

Terminologia

Hibrido Vs Headless

Este guia explica como o site da documentação obtém carregamentos rápidos de páginas estáticas enquanto mantém a funcionalidade do modo de edição do CMS.

Arquitetura de Rotas Duplas

Utilizamos duas rotas para o mesmo conteúdo:

app/
├── [...slug]/page.tsx          # Produção: force-static (rápido)
└── preview/[...slug]/page.tsx  # Modo de edição: force-dynamic (lê searchParams)

Um middleware de proxy reescreve transparentemente as solicitações de modo de edição:

Usuário solicita: /en/headless/quickstart?edit_mode=true
       ↓
Proxy detecta ?edit_mode=true
       ↓
Reescrita interna para: /preview/en/headless/quickstart?edit_mode=true
       ↓
Rota dinâmica renderiza com wrappers de edição

O usuário nunca vê /preview na sua URL - é uma reescrita interna.

Como Funciona

Caminho de Produção (Padrão)

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

export default async function Page({ params }) {
  // Sem searchParams - a página é totalmente estática
  
  • Páginas são pré-renderizadas durante o build
  • Servidas instantaneamente a partir do cache edge da CDN
  • Revalidadas a cada 60 segundos (ISR) como rede de segurança

Caminho do Modo de Edição

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

export default async function PreviewPage({ params, searchParams }) {
  // searchParams disponível - pode detectar edit_mode
  return <ParametricRoutePage params={params
  • Renderizada em cada requisição
  • Pode ler ?edit_mode=true da URL
  • Renderiza com wrappers editáveis do CMS e contornos de blocos

A Reescrita do Proxy

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

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

Comparação de Desempenho

CenárioTempo de respostaRenderização
Página de produção (em cache)~50-100msEstática da CDN
Página de produção (defasada)~50-100ms + atualização em segundo planoEstática, depois ISR
Modo de edição~500-1500msSSR dinâmico

Entendendo ISR (Incremental Static Regeneration)

A configuração revalidate = 60 habilita o ISR. Isso NÃO significa que as páginas são recomputadas a cada 60 segundos.

ISR usa um padrão stale-while-revalidate:

Chega uma requisição:
  → A página em cache tem < 60s? → Servir do cache (instantâneo)
  → A página em cache tem > 60s? → Servir cache obsoleto (instantâneo)
                                + revalidar em segundo plano para a próxima requisição

Sem requisições = Sem recomputação. Nunca.

Exemplo:

  • Página em cache às 10h00
  • Sem visitantes até as 15h00
  • Primeiro visitante às 15h00 recebe o cache obsoleto instantaneamente
  • Atualização em segundo plano acontece, próximo visitante recebe conteúdo fresco

A janela de 60 segundos é uma rede de segurança. Idealmente, usaríamos revalidação sob demanda via webhooks quando o conteúdo do CMS mudar.

Quando Usar Cada Rota

Caso de usoURLRota utilizada
Navegação normal/en/headless/quickstartEstática
Construtor de templates do CMS/en/headless/quickstart?edit_mode=truePreview (via reescrita)
Preview de bloco de IA/en/headless/quickstart?ai_preview=1Preview (via reescrita)

Por que Não Usar Apenas Renderização Dinâmica?

A abordagem simples (sem force-static, sem rota de preview) funciona, mas é lenta:

// Abordagem simples - funciona, mas leva ~1-2s por requisição
export default async function Page({ params, searchParams }) {
  return <ParametricRoutePage params={params} searchParams={searchParams} />;
}

Isso renderiza dinamicamente em cada requisição. Para um site de documentação com muitas páginas, isso significa:

  • Inicializações a frio em cada página
  • Sem benefício de cache na borda da CDN
  • Tempos de carregamento de 1-2 segundos vs milissegundos

A arquitetura de rotas duplas nos dá o melhor dos dois mundos: velocidade estática para leitores e funcionalidade dinâmica para editores.

return
<
ParametricRoutePage
params
={
params
} />;
}
}
searchParams
={
searchParams
} />;
}
const
aiPreview
=
searchParams.
get
(
'ai_preview'
);
// Reescreve para a rota de preview se edit_mode ou ai_preview estiver presente
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();
};