Nuxt Server-Side Props

You can fetch server-side content directly from pages!
NuxtVue

Início

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

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.

Quando Usar Cada Uma

ComposableServidorClienteEventosSó SSR
getServerSide✅ Executa✅ Recebe resultado❌ Não✅ Sim
serverOnly✅ Executa❌ Undefined❌ Não✅ Sim
clientOnly❌ Undefined✅ Executa✅ Sim❌ Não

Resumo:

  • Só onLoad / top-level: getServerSide, serverOnly (SSR)
  • Pronta para eventos: clientOnly (browser)

Como usar

As 3 funções são relativamente fáceis de usar. São todas invocadas quase do mesmo jeito e são simples.

  1. 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:

  • Função síncrona / "default"
const serverData = await getServerSide(() => {
    return very_important_server_logic();
});
  • Função async
    Necessário sempre que usar import
const asyncServerData = await getServerSide(async () => {
    const fetchServer = await import("#server/utils/mainFetch");
    return await fetchServer();
});
  • Chave / Key manual
    A "chave" é tratada automaticamente. Mas em loops (for & while) e if statements, é preciso uma chave manual
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
}
  1. 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
  1. clientOnly

Esta 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
})

Behind the Scenes...

  • 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.
  • Chaves são auto-injetadas pelo 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.