nuxt logo

Tradução da Documentação (Não Oficial)

Nuxt.js
Version:v3.17

Modos de Renderização

Aprenda sobre os diferentes modos de renderização disponíveis no Nuxt.

O Nuxt suporta diferentes modos de renderização, renderização universal, renderização no lado do cliente, mas também oferece renderização híbrida e a possibilidade de renderizar sua aplicação em servidores de borda de CDN.

Tanto o navegador quanto o servidor podem interpretar o código JavaScript para transformar componentes Vue.js em elementos HTML. Esta etapa é chamada de renderização. O Nuxt suporta tanto a renderização universal quanto a no lado do cliente. As duas abordagens têm benefícios e desvantagens que iremos cobrir.

Por padrão, o Nuxt usa a renderização universal para proporcionar uma melhor experiência ao usuário, desempenho e otimizar a indexação por motores de busca, mas você pode mudar os modos de renderização em uma linha de configuração.

Renderização Universal

Esta etapa é semelhante à tradicional renderização no lado do servidor realizada por aplicações PHP ou Ruby. Quando o navegador solicita uma URL com a renderização universal habilitada, o Nuxt executa o código JavaScript (Vue.js) em um ambiente de servidor e retorna uma página HTML totalmente renderizada para o navegador. O Nuxt também pode retornar uma página HTML totalmente renderizada a partir de um cache se a página foi gerada antecipadamente. Os usuários recebem imediatamente todo o conteúdo inicial da aplicação, ao contrário da renderização no lado do cliente.

Uma vez que o documento HTML foi baixado, o navegador interpreta isso e o Vue.js assume o controle do documento. O mesmo código JavaScript que uma vez foi executado no servidor é executado no cliente (navegador) novamente em segundo plano, agora permitindo interatividade (daí a renderização universal) ao vincular seus ouvintes ao HTML. Isso é chamado de Hidratação. Quando a hidratação é concluída, a página pode desfrutar de benefícios como interfaces dinâmicas e transições de página.

A renderização universal permite que uma aplicação Nuxt forneça tempos de carregamento de página rápidos enquanto preserva os benefícios da renderização no lado do cliente. Além disso, como o conteúdo já está presente no documento HTML, os rastreadores podem indexá-lo sem sobrecarga.

Os usuários podem acessar o conteúdo estático quando o documento HTML é carregado. A hidratação então permite a interatividade da página

O que é renderizado no servidor e o que é renderizado no cliente?

É normal perguntar quais partes de um arquivo Vue são executadas no servidor e/ou no cliente no modo de renderização universal.

app.vue
<script setup lang="ts">
const counter = ref(0); // executa em ambientes de servidor e cliente

const handleClick = () => {
  counter.value++; // executa apenas em um ambiente de cliente
};
</script>

<template>
  <div>
    <p>Count: {{ counter }}</p>
    <button @click="handleClick">Increment</button>
  </div>
</template>

Na solicitação inicial, a referência counter é inicializada no servidor, pois é renderizada dentro da tag <p>. O conteúdo de handleClick nunca é executado aqui. Durante a hidratação no navegador, a referência counter é reinicializada. O handleClick finalmente se vincula ao botão; Portanto, é razoável deduzir que o corpo de handleClick sempre será executado em um ambiente de navegador.

Middlewares e páginas são executados no servidor e no cliente durante a hidratação. Plugins podem ser renderizados no servidor ou cliente ou ambos. Componentes podem ser forçados a executar apenas no cliente. Composables e utilitários são renderizados com base no contexto de seu uso.

Benefícios da renderização no lado do servidor:

  • Desempenho: Os usuários podem acessar imediatamente o conteúdo da página porque os navegadores podem exibir conteúdo estático muito mais rápido do que conteúdo gerado por JavaScript. Ao mesmo tempo, o Nuxt preserva a interatividade de uma aplicação web durante o processo de hidratação.
  • Otimização para Motores de Busca: A renderização universal entrega todo o conteúdo HTML da página para o navegador como uma aplicação clássica de servidor. Os rastreadores da web podem indexar diretamente o conteúdo da página, o que torna a renderização universal uma ótima escolha para qualquer conteúdo que você deseja indexar rapidamente.

Desvantagens da renderização no lado do servidor:

  • Restrições de desenvolvimento: Os ambientes de servidor e navegador não fornecem as mesmas APIs, e pode ser complicado escrever código que possa ser executado em ambos os lados sem problemas. Felizmente, o Nuxt fornece diretrizes e variáveis específicas para ajudá-lo a determinar onde um pedaço de código é executado.
  • Custo: Um servidor precisa estar em execução para renderizar páginas sob demanda. Isso adiciona um custo mensal como qualquer servidor tradicional. No entanto, as chamadas ao servidor são altamente reduzidas graças à renderização universal com o navegador assumindo a navegação no lado do cliente. Uma redução de custo é possível aproveitando a renderização na borda.

A renderização universal é muito versátil e pode se adequar a quase qualquer caso de uso, sendo especialmente apropriada para qualquer site orientado a conteúdo: blogs, sites de marketing, portfólios, sites de e-commerce e marketplaces.

Para mais exemplos sobre como escrever código Vue sem incompatibilidade de hidratação, veja a documentação do Vue.

Ao importar uma biblioteca que depende de APIs do navegador e tem efeitos colaterais, certifique-se de que o componente que a importa seja chamado apenas no lado do cliente. Os empacotadores não removem automaticamente as importações de módulos que contêm efeitos colaterais.

Renderização no Lado do Cliente

Por padrão, uma aplicação Vue.js tradicional é renderizada no navegador (ou cliente). Em seguida, o Vue.js gera elementos HTML após o navegador baixar e analisar todo o código JavaScript contendo as instruções para criar a interface atual.

Os usuários têm que esperar o navegador baixar, analisar e executar o JavaScript antes de ver o conteúdo da página

Benefícios da renderização no lado do cliente:

  • Velocidade de desenvolvimento: Ao trabalhar inteiramente no lado do cliente, não precisamos nos preocupar com a compatibilidade do código com o servidor, por exemplo, usando APIs exclusivas do navegador como o objeto window.
  • Mais barato: Executar um servidor adiciona um custo de infraestrutura, pois você precisaria rodar em uma plataforma que suporte JavaScript. Podemos hospedar aplicações apenas no cliente em qualquer servidor estático com arquivos HTML, CSS e JavaScript.
  • Offline: Como o código é executado inteiramente no navegador, ele pode continuar funcionando bem enquanto a internet estiver indisponível.

Desvantagens da renderização no lado do cliente:

  • Desempenho: O usuário tem que esperar o navegador baixar, analisar e executar os arquivos JavaScript. Dependendo da rede para a parte de download e do dispositivo do usuário para a análise e execução, isso pode levar algum tempo e impactar a experiência do usuário.
  • Otimização para Motores de Busca: Indexar e atualizar o conteúdo entregue via renderização no lado do cliente leva mais tempo do que com um documento HTML renderizado no servidor. Isso está relacionado à desvantagem de desempenho que discutimos, pois os rastreadores de motores de busca não esperarão que a interface seja totalmente renderizada em sua primeira tentativa de indexar a página. Seu conteúdo levará mais tempo para aparecer e ser atualizado nas páginas de resultados de busca com renderização puramente no lado do cliente.

A renderização no lado do cliente é uma boa escolha para aplicações web altamente interativas que não precisam de indexação ou cujos usuários visitam frequentemente. Ela pode aproveitar o cache do navegador para pular a fase de download em visitas subsequentes, como SaaS, aplicações de back-office ou jogos online.

Você pode habilitar a renderização apenas no lado do cliente com o Nuxt no seu nuxt.config.ts:

nuxt.config.ts
export default defineNuxtConfig({
  ssr: false
})

Se você usar ssr: false, também deve colocar um arquivo HTML em ~/app/spa-loading-template.html com algum HTML que você gostaria de usar para renderizar uma tela de carregamento que será renderizada até que sua aplicação seja hidratada.

Veja também Template de Carregamento SPA

Implantando uma Aplicação Estática Renderizada no Cliente

Se você implantar sua aplicação em hospedagem estática com os comandos nuxt generate ou nuxt build --prerender, então por padrão, o Nuxt renderizará cada página como um arquivo HTML estático separado.

Se você pré-renderizar sua aplicação com os comandos nuxt generate ou nuxt build --prerender, então você não poderá usar nenhum endpoint de servidor, pois nenhum servidor será incluído na sua pasta de saída. Se você precisar de funcionalidade de servidor, use nuxt build em vez disso.

Se você estiver usando renderização puramente no lado do cliente, isso pode ser desnecessário. Você pode precisar apenas de um único arquivo index.html, além de 200.html e 404.html como fallback, que você pode instruir seu host web estático a servir para todas as solicitações.

Para conseguir isso, podemos mudar como as rotas são pré-renderizadas. Basta adicionar isso aos seus hooks no seu nuxt.config.ts:

nuxt.config.ts
export default defineNuxtConfig({
  hooks: {
    'prerender:routes' ({ routes }) {
      routes.clear() // Não gerar nenhuma rota (exceto as padrões)
    }
  },
})

Isso produzirá três arquivos:

  • index.html
  • 200.html
  • 404.html

Os arquivos 200.html e 404.html podem ser úteis para o provedor de hospedagem que você está usando.

Pulando a Geração de Fallback do Cliente

Ao pré-renderizar uma aplicação renderizada no cliente, o Nuxt gerará por padrão os arquivos index.html, 200.html e 404.html. No entanto, se você precisar impedir que qualquer um (ou todos) desses arquivos sejam gerados na sua build, você pode usar o hook 'prerender:generate' do Nitro.

nuxt.config.ts
export default defineNuxtConfig({
  ssr: false,
  nitro: {
    hooks: {
      'prerender:generate'(route) {
        const routesToSkip = ['/index.html', '/200.html', '/404.html']
        if (routesToSkip.includes(route.route)) {
          route.skip = true
        }
      }
    }
  }
})

Renderização Híbrida

A renderização híbrida permite diferentes regras de cache por rota usando Regras de Rota e decide como o servidor deve responder a uma nova solicitação em uma URL específica.

Anteriormente, cada rota/página de uma aplicação Nuxt e servidor devia usar o mesmo modo de renderização, universal ou no lado do cliente. Em vários casos, algumas páginas poderiam ser geradas no momento da build, enquanto outras deveriam ser renderizadas no lado do cliente. Por exemplo, pense em um site de conteúdo com uma seção de administração. Cada página de conteúdo deve ser principalmente estática e gerada uma vez, mas a seção de administração requer registro e se comporta mais como uma aplicação dinâmica.

O Nuxt inclui suporte a regras de rota e renderização híbrida. Usando regras de rota, você pode definir regras para um grupo de rotas do nuxt, mudar o modo de renderização ou atribuir uma estratégia de cache com base na rota!

O servidor Nuxt registrará automaticamente o middleware correspondente e envolverá as rotas com manipuladores de cache usando a camada de cache do Nitro.

nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    // Página inicial pré-renderizada no momento da build
    '/': { prerender: true },
    // Página de produtos gerada sob demanda, revalida em segundo plano, armazenada em cache até que a resposta da API mude
    '/products': { swr: true },
    // Páginas de produtos geradas sob demanda, revalidam em segundo plano, armazenadas em cache por 1 hora (3600 segundos)
    '/products/**': { swr: 3600 },
    // Página de postagens do blog gerada sob demanda, revalida em segundo plano, armazenada em cache na CDN por 1 hora (3600 segundos)
    '/blog': { isr: 3600 },
    // Página de postagem do blog gerada sob demanda uma vez até o próximo deployment, armazenada em cache na CDN
    '/blog/**': { isr: true },
    // Painel de administração renderiza apenas no lado do cliente
    '/admin/**': { ssr: false },
    // Adiciona cabeçalhos cors em rotas de API
    '/api/**': { cors: true },
    // Redireciona URLs legados
    '/old-page': { redirect: '/new-page' }
  }
})

Regras de Rota

As diferentes propriedades que você pode usar são as seguintes:

  • redirect: string - Define redirecionamentos no lado do servidor.
  • ssr: boolean - Desativa a renderização no lado do servidor do HTML para seções da sua aplicação e faz com que sejam renderizadas apenas no navegador com ssr: false
  • cors: boolean - Adiciona automaticamente cabeçalhos cors com cors: true - você pode personalizar a saída substituindo com headers
  • headers: object - Adiciona cabeçalhos específicos a seções do seu site - por exemplo, seus ativos
  • swr: number | boolean - Adiciona cabeçalhos de cache à resposta do servidor e a armazena em cache no servidor ou proxy reverso por um TTL (tempo de vida) configurável. O preset node-server do Nitro é capaz de armazenar em cache a resposta completa. Quando o TTL expira, a resposta em cache será enviada enquanto a página será regenerada em segundo plano. Se true for usado, um cabeçalho stale-while-revalidate é adicionado sem um MaxAge.
  • isr: number | boolean - O comportamento é o mesmo que swr, exceto que podemos adicionar a resposta ao cache da CDN em plataformas que suportam isso (atualmente Netlify ou Vercel). Se true for usado, o conteúdo persiste até o próximo deploy dentro da CDN.
  • prerender: boolean - Pré-renderiza rotas no momento da build e as inclui na sua build como ativos estáticos
  • noScripts: boolean - Desativa a renderização de scripts Nuxt e dicas de recursos JS para seções do seu site.
  • appMiddleware: string | string[] | Record<string, boolean> - Permite definir middleware que deve ou não ser executado para caminhos de página dentro da parte da aplicação Vue do seu aplicativo (ou seja, não suas rotas Nitro)

Sempre que possível, as regras de rota serão aplicadas automaticamente às regras nativas da plataforma de implantação para desempenho ideal (Netlify e Vercel são atualmente suportados).

Note que a Renderização Híbrida não está disponível quando se usa nuxt generate.

Exemplos:

Renderização na Borda

A Renderização na Borda (ESR) é um recurso poderoso introduzido no Nuxt que permite a renderização da sua aplicação Nuxt mais próxima dos seus usuários através dos servidores de borda de uma Rede de Distribuição de Conteúdo (CDN). Ao aproveitar o ESR, você pode garantir um desempenho melhorado e latência reduzida, proporcionando assim uma experiência de usuário aprimorada.

Com o ESR, o processo de renderização é empurrado para a 'borda' da rede - os servidores de borda da CDN. Note que o ESR é mais um alvo de implantação do que um modo de renderização real.

Quando uma solicitação para uma página é feita, em vez de ir até o servidor original, ela é interceptada pelo servidor de borda mais próximo. Este servidor gera o HTML para a página e o envia de volta ao usuário. Este processo minimiza a distância física que os dados precisam percorrer, reduzindo a latência e carregando a página mais rapidamente.

A renderização na borda é possível graças ao Nitro, o motor de servidor que alimenta o Nuxt. Ele oferece suporte multiplataforma para Node.js, Deno, Cloudflare Workers e mais.

As plataformas atuais onde você pode aproveitar o ESR são:

  • Cloudflare Pages com configuração zero usando a integração git e o comando nuxt build
  • Vercel Edge Functions usando o comando nuxt build e a variável de ambiente NITRO_PRESET=vercel-edge
  • Netlify Edge Functions usando o comando nuxt build e a variável de ambiente NITRO_PRESET=netlify-edge

Note que a Renderização Híbrida pode ser usada quando se utiliza a Renderização na Borda com regras de rota.

Você pode explorar exemplos de código aberto implantados em algumas das plataformas mencionadas acima: