# Nuxt 3: SSR e geração estática, o guia completo > Domine o SSR e a geração estática com o Nuxt 3. De useFetch às route rules, aprenda a otimizar o desempenho das suas aplicações Vue.js. - Published: 2026-02-11 - Updated: 2026-04-28 - Author: SharpSkill - Tags: nuxt 3, vue.js, ssr, geração estática, performance web - Reading time: 12 min --- O Nuxt 3 transforma a maneira como aplicações Vue.js são construídas, oferecendo múltiplos modos de renderização adaptados a diferentes casos de uso. Do Server-Side Rendering (SSR) à geração estática e à renderização híbrida, o framework oferece uma flexibilidade notável para otimizar desempenho e SEO. > **Pré-requisitos** > > Este tutorial assume conhecimento básico de Vue 3 e da Composition API. Familiaridade com conceitos de renderização no servidor é útil, mas não é obrigatória, já que os fundamentos são explicados ao longo do guia. ## Compreender os modos de renderização do Nuxt 3 Antes de mergulhar no código, é essencial entender as diferenças entre os modos de renderização disponíveis. Cada modo atende a necessidades específicas em termos de desempenho, SEO e experiência do usuário. O SSR (Server-Side Rendering) gera o HTML no servidor a cada requisição. A geração estática (SSG) pré-gera todas as páginas no momento do build. O modo híbrido permite combinar essas abordagens página por página. ```typescript // nuxt.config.ts // Configuração dos diferentes modos de renderização export default defineNuxtConfig({ // SSR ativado por padrão (recomendado para SEO) ssr: true, // Geração estática: pré-renderiza todas as páginas // Use 'npm run generate' para fazer o build // target: 'static', // Sintaxe Nuxt 2 // Modo híbrido: configurável por rota routeRules: { // Página inicial: pré-renderizada e em cache '/': { prerender: true }, // Blog: geração estática '/blog/**': { prerender: true }, // Dashboard: renderização apenas no cliente '/dashboard/**': { ssr: false }, // API: sem pré-renderização '/api/**': { prerender: false } } }) ``` Essa configuração demonstra o poder do modo híbrido: cada seção da aplicação utiliza o modo de renderização mais adequado às suas necessidades. ## Busca de dados com useFetch e useAsyncData O Nuxt 3 oferece dois composables principais para buscar dados de forma isomórfica. Esses composables funcionam tanto no servidor quanto no cliente, com gestão automática da hidratação. `useFetch` é um wrapper em torno de `useAsyncData` que simplifica chamadas HTTP. `useAsyncData` oferece mais controle para casos de uso avançados. ```vue ``` Para casos que exigem mais controle, `useAsyncData` permite executar qualquer função assíncrona. ```vue ``` Esses composables evitam duplo fetching: os dados obtidos no servidor são serializados no payload HTML e reutilizados durante a hidratação no cliente. ## Personalizar o SSR com server hooks O SSR do Nuxt 3 pode ser personalizado por meio de server hooks. Esses hooks permitem intervir em diferentes etapas do ciclo de renderização para modificar o comportamento padrão. ```typescript // server/plugins/render-hooks.ts // Plugin de servidor para personalizar a renderização SSR export default defineNitroPlugin((nitroApp) => { // Hook executado antes da renderização de cada página nitroApp.hooks.hook('render:html', (html, { event }) => { // Injetar scripts ou metadados html.head.push(` `) }) // Hook para gestão do cache de renderização nitroApp.hooks.hook('render:response', (response, { event }) => { // Adicionar cabeçalhos de cache personalizados const path = event.path if (path.startsWith('/blog/')) { // Cache longo para artigos do blog response.headers['Cache-Control'] = 'public, max-age=3600, s-maxage=86400' } else if (path.startsWith('/api/')) { // Sem cache para APIs response.headers['Cache-Control'] = 'no-store' } }) }) ``` > **Desempenho do SSR** > > O hook `render:response` é ideal para implementar estratégias de cache HTTP. Combinar SSR com um CDN que respeite os cabeçalhos Cache-Control permite servir páginas pré-renderizadas mantendo a capacidade de invalidá-las. ## Geração estática com nuxt generate A geração estática pré-constrói todas as páginas no momento do build. Essa abordagem é ideal para sites com conteúdo estável como blogs, documentação ou sites de marketing. Para rotas dinâmicas, o Nuxt precisa conhecer todas as URLs a gerar. O hook `prerender:routes` permite definir essas rotas de forma programática. ```typescript // nuxt.config.ts // Configuração completa para geração estática export default defineNuxtConfig({ // Ativar geração estática nitro: { prerender: { // Ativar o crawling automático de links crawlLinks: true, // Rotas a sempre incluir routes: ['/', '/about', '/contact'], // Ignorar certas rotas ignore: ['/admin', '/api'] } }, hooks: { // Hook para gerar rotas dinâmicas async 'prerender:routes'(ctx) { // Buscar artigos da API ou BD const articles = await fetch('https://api.example.com/articles') .then(res => res.json()) // Adicionar rotas de artigos for (const article of articles) { ctx.routes.add(`/blog/${article.slug}`) } // Buscar categorias const categories = await fetch('https://api.example.com/categories') .then(res => res.json()) for (const category of categories) { ctx.routes.add(`/category/${category.slug}`) } } } }) ``` Para projetos com muitas páginas, o crawler automático pode ser insuficiente. Eis uma abordagem mais robusta com um arquivo de configuração separado. ```typescript // server/utils/generate-routes.ts // Utilitário para gerar a lista de rotas dinâmicas import { prisma } from './prisma' export async function getAllStaticRoutes(): Promise { const routes: string[] = [] // Artigos do blog const articles = await prisma.article.findMany({ where: { published: true }, select: { slug: true, category: { select: { slug: true } } } }) for (const article of articles) { routes.push(`/blog/${article.category.slug}/${article.slug}`) } // Páginas de produtos const products = await prisma.product.findMany({ where: { active: true }, select: { slug: true } }) for (const product of products) { routes.push(`/products/${product.slug}`) } // Páginas de tags const tags = await prisma.tag.findMany({ select: { slug: true } }) for (const tag of tags) { routes.push(`/tags/${tag.slug}`) } return routes } ``` ## Renderização híbrida com routeRules A renderização híbrida é o recurso de destaque do Nuxt 3. Permite definir regras de renderização diferentes por rota, combinando o melhor do SSR e do SSG. ```typescript // nuxt.config.ts // Configuração avançada de renderização híbrida export default defineNuxtConfig({ routeRules: { // Páginas de marketing: pré-renderizadas e em cache de longo prazo '/': { prerender: true }, '/pricing': { prerender: true }, '/features/**': { prerender: true }, // Blog: ISR (Incremental Static Regeneration) // Revalidação a cada hora '/blog/**': { isr: 3600, prerender: true }, // Documentação: cache CDN com revalidação '/docs/**': { swr: 86400, // Stale-while-revalidate prerender: true }, // E-commerce: SSR com cache curto '/products/**': { ssr: true, cache: { maxAge: 60, staleMaxAge: 300 } }, // Carrinho e checkout: somente cliente '/cart': { ssr: false }, '/checkout/**': { ssr: false }, // Dashboard: modo SPA '/dashboard/**': { ssr: false, // Desativar pré-renderização prerender: false }, // Rotas API: sem cache por padrão '/api/**': { cors: true, headers: { 'Access-Control-Allow-Methods': 'GET,POST,PUT,DELETE' } } } }) ``` Essa configuração ilustra uma arquitetura típica de aplicação moderna: páginas públicas são otimizadas para SEO com SSG, enquanto seções interativas usam renderização no cliente. ## Otimização de desempenho com cache de dados Além do cache de páginas, o Nuxt 3 permite cachear os dados buscados. Essa estratégia reduz a carga sobre as APIs e melhora os tempos de resposta. ```typescript // server/api/articles/[slug].get.ts // Endpoint API com cache de dados import { getArticleBySlug } from '~/server/utils/articles' export default defineCachedEventHandler( async (event) => { const slug = getRouterParam(event, 'slug') if (!slug) { throw createError({ statusCode: 400, message: 'Slug ausente' }) } const article = await getArticleBySlug(slug) if (!article) { throw createError({ statusCode: 404, message: 'Artigo não encontrado' }) } return article }, { // Chave de cache baseada no slug getKey: (event) => `article-${getRouterParam(event, 'slug')}`, // Duração do cache: 1 hora maxAge: 3600, // Stale-while-revalidate: servir cache obsoleto durante a atualização staleMaxAge: 7200, // Invalidação baseada em tags tags: ['articles'] } ) ``` Para invalidar o cache quando o conteúdo muda, o Nuxt fornece um sistema de tags. ```typescript // server/api/articles/[slug].put.ts // Atualização de artigo com invalidação de cache import { updateArticle } from '~/server/utils/articles' export default defineEventHandler(async (event) => { const slug = getRouterParam(event, 'slug') const body = await readBody(event) // Atualizar o artigo const article = await updateArticle(slug, body) // Invalidar o cache deste artigo await useStorage('cache').removeItem(`nitro:handlers:article-${slug}`) // Ou invalidação baseada em tags (todos os artigos) // await useStorage('cache').clear('articles') return article }) ``` > **Cache distribuído** > > Em produção com múltiplas instâncias, o cache em memória é insuficiente. Recomenda-se configurar Redis ou outro sistema distribuído via configuração do Nitro para garantir consistência entre instâncias. ## Gestão de SEO e metadados O SSR permite otimizar o SEO ao gerar metadados no servidor. O Nuxt 3 oferece várias abordagens para gerenciar meta tags de forma dinâmica. ```vue ``` Para páginas estáticas, os metadados podem ser definidos diretamente no componente. ```vue ``` ## Implantação e considerações de produção A escolha da implantação depende do modo de renderização utilizado. Eis as principais opções e suas configurações. ```typescript // nuxt.config.ts // Configuração para diferentes ambientes de implantação export default defineNuxtConfig({ nitro: { // Preset conforme a plataforma alvo // preset: 'vercel', // Vercel // preset: 'netlify', // Netlify // preset: 'cloudflare-pages', // Cloudflare // preset: 'node-server', // Node.js clássico // Configuração para Node.js em produção preset: 'node-server', // Compressão de respostas compressPublicAssets: true, // Configuração do armazenamento de cache storage: { cache: { driver: 'redis', url: process.env.REDIS_URL } } }, // Variáveis de ambiente em runtime runtimeConfig: { // Segredos (não expostos ao cliente) apiSecret: process.env.API_SECRET, // Configuração pública public: { apiBase: process.env.NUXT_PUBLIC_API_BASE || '/api' } } }) ``` Para implantação estática, o comando `npm run generate` cria uma pasta `.output/public` pronta para implantar em qualquer host de arquivos estáticos. ```bash # Geração estática npm run generate # O conteúdo de .output/public pode ser implantado em: # - Vercel (detecção automática) # - Netlify (configuração automática) # - GitHub Pages # - S3 + CloudFront # - Qualquer CDN ou servidor de arquivos estáticos ``` ## Conclusão O Nuxt 3 oferece flexibilidade excepcional para renderizar aplicações Vue.js. A escolha entre SSR, SSG e renderização híbrida depende das necessidades específicas de cada projeto. **Pontos-chave:** ✅ **SSR**: ideal para conteúdo dinâmico que exige bom SEO (e-commerce, sites de notícias) ✅ **SSG**: perfeito para conteúdo estável (blogs, documentação, sites de marketing) ✅ **Híbrido**: a melhor abordagem para aplicações complexas com necessidades variadas ✅ **useFetch/useAsyncData**: hidratação automática e gestão de cache ✅ **routeRules**: configuração granular para o comportamento de cada rota ✅ **Cache**: múltiplas estratégias para otimizar o desempenho em produção Combinar a renderização híbrida com uma estratégia de cache bem pensada permite construir aplicações performáticas otimizadas para SEO, mantendo a interatividade das Single Page Applications. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/pt/blog/vue-nuxt/nuxt-3-ssr-static-generation