SSR e Hydration (Next, Nuxt, Angular Universal)
Ao trabalhar com frameworks de SSR (Server-Side Rendering) ou SSG (Static Site Generation), o HTML é gerado em um ambiente Node.js, onde objetos de janela (window e document) não existem.
Uma vez que Web Components, por sua própria natureza, dependem das APIs nativas do navegador (como customElements.define e HTMLElement), eles requerem uma abordagem de Hydration (Hidratação) específica.
Os componentes GovBR-DS são construídos com StencilJS, que suporta hidratação SSR via "Declarative Shadow DOM", reduzindo os clássicos sobressaltos visuais de hidratação (FOUC).
Abaixo detalhamos estratégias de como lidar com os Web Components em Next.js e frameworks similares.
Next.js (App Router)
A abordagem mais moderna no React 18 e Next.js App Router usa Server Components. Porém, como Web Components dependem do navegador para inicialização interativa, seus arquivos de inicialização devem ser marcados com 'use client'.
- Crie um componente cliente para o Registry:
// components/GovbrRegistry.tsx
'use client'
import { useEffect } from 'react';
import { defineCustomElements } from '@govbr-ds/webcomponents/loader';
import '@govbr-ds/core/dist/core.min.css'; // Estilos globais
export default function GovbrRegistry({ children }: { children: React.ReactNode }) {
useEffect(() => {
// Isso será executado apenas no navegador, e registrará todos os elementos
defineCustomElements(window);
}, []);
return <>{children}</>;
}
- Englobe seu Layout Principal:
// app/layout.tsx
import GovbrRegistry from '../components/GovbrRegistry';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="pt-BR">
<body>
<GovbrRegistry>
{children}
</GovbrRegistry>
</body>
</html>
);
}
Dessa forma, os wrappers React exportados em @govbr-ds/webcomponents-react (<br-button>, <br-input>, etc.) podem ser utilizados em arquivos de cliente e serão hidratados com segurança sem disparar erros de SSR, pois o React entende que eles emitem seu próprio HTML pre-renderizado.
Nuxt.js 3
O Nuxt.js e o Vue trabalham excepcionalmente bem com Custom Elements, mas o compilador do Vue precisa saber que tags começando com br- não são componentes Vue e sim componentes da plataforma nativa, para que ele não tente resolvê-los no lado do servidor.
No seu arquivo de configuração nuxt.config.ts:
export default defineNuxtConfig({
vue: {
compilerOptions: {
isCustomElement: (tag) => tag.startsWith('br-')
}
},
plugins: [
{ src: '~/plugins/govbr.client.ts', mode: 'client' }
]
})
E no seu plugin de cliente, faça o carregamento do defineCustomElements da mesma maneira.
Evitando o FOUC (Flash of Unstyled Content)
Um dos problemas clássicos com SSR e Web Components é o FOUC — um piscar de componentes sem estilo enquanto o JavaScript carrega e o customElements.define ainda não rodou.
Solução recomendada:
Sempre importe as classes base e tokens de estilo nativos do pacote core globalmente. Mesmo se o Web Component não tiver inicializado as interações e o Shadow DOM, sua "casca" principal terá as regras globais e a aparência ficará muito próxima da versão hidratada. O componente fará o upgrade silenciosamente ao terminar o download do bundle.