Todos sabem que o NextJS tem getServerSideProps(). Podes com isso, rodar código "sensível" como db e ficheiros porque a função só roda server-side, e o resultado aparece no client também.
Embora agora o React tenha RSC (React Server Components), a.k.a. "use server" , Nuxt não tem nenhum equivalente.
Até agora, se quisesses código Server-Side tinhas de criar uma server-route.
Com este projeto, podes colocar código Server-Side diretamente em páginas, composables, componentes, enfim qualquer parte de #app.
Até mesmo #server imports functionam (usando import dinâmico)
O projeto é simples porque este problema também é simples.
Encontrar uma maneira de fazer funções server-only é algo que falta no Nuxt.
Portanto eu criei 3 funções prontas para ser usadas:
getServerSide() ---> Executa server-side e hidrata o resultado (ambos o servidor e o cliente ficam com o resultado). (resultado = return)serverOnly() ---> Executa server-side sem hidratar. Em SSR, o resultado existe. O cliente não vê nada.clientOnly() ---> Execute client-side. O servidor não vê nada.| Composable | Servidor | Cliente | Eventos | Só SSR |
|---|---|---|---|---|
getServerSide | ✅ Executa | ✅ Recebe resultado | ❌ Não | ✅ Sim |
serverOnly | ✅ Executa | ❌ Undefined | ❌ Não | ✅ Sim |
clientOnly | ❌ Undefined | ✅ Executa | ✅ Sim | ❌ Não |
Resumo:
getServerSide, serverOnly (SSR)clientOnly (browser)As 3 funções são relativamente fáceis de usar. São todas invocadas quase do mesmo jeito e são simples.
getServerSide()A função principal. Ela injeta o resultado em payload para o cliente com uma chave especial para garantir hidratação.
Só funciona em top-level / onLoad.
Chamar depois da página ser carrgeada NÃO vai funcionar (@click events por exemplo).
Exemplos:
const serverData = await getServerSide(() => {
return very_important_server_logic();
});
const asyncServerData = await getServerSide(async () => {
const fetchServer = await import("#server/utils/mainFetch");
return await fetchServer();
});
let manualKeyServerData: any;
if (some_condition) {
manualKeyServerData = await getServerSide(() => {
return very_important_server_logic();
}, "my-manual-key"); // a chave coloca-se depois da função
}
serverOnly()Semelhante uso. Não há hidratação nem chave.
Executa e retorna Server-Side.
Só funciona em top-level / onLoad.
Chamar depois da página ser carrgeada NÃO vai funcionar (@click events por exemplo).
O cliente recebe undefined.
// sync / default
const SSR_only = await serverOnly(() => {
return very_important_server_logic();
})
// async
// use this when importing
const async_SSR_only = await serverOnly(async () => {
const { write_to_db } = await import("#server/utils/db_utils")
return await write_to_db(params);
});
// you can use the result safely.
// client sees undefined
clientOnlyEsta função vai sempre retornar undefined no servidor.
É seguro usar window, document, e todos os objetos de cliente do JavaScript.
const myOwnBody = await clientOnly(() => {
return document.body.getHTML();
})
const asyncClientOnlyt = await clientOnly(async () => {
// async logic here
})
getServerSide usa import.meta.server para executar fn e escrever o resultado diretamente em nuxtApp.payload. No cliente, lê do payload — sem fetch, sem re-execução.serverOnly e clientOnly usam flags compile-time import.meta.server / import.meta.client. Vite remove o ramo morto completamente em build time — o código servidor nunca chega ao bundle cliente.keyedComposables do Nuxt — cada call site recebe um hash estável baseado em file path e line number, o mesmo mecanismo de useState e useAsyncData.