Como Reduzimos Respostas Lentas em 80%
A Subito é um dos principais marketplaces da Itália. Lidamos com milhares de requisições a cada minuto. Nossa página de detalhes do anúncio é vital para o SEO e para a receita.
Migramos esta página do Next.js Pages Router para o App Router. Não interrompemos o desenvolvimento de novos produtos para realizar isso. Avançamos em pequenos passos.
Aqui está como fizemos.
A Abordagem
Utilizamos uma estratégia incremental. Adicionamos a árvore do App Router ao lado do antigo Pages Router. Isso nos permitiu lançar novos recursos enquanto realizávamos a migração.
Utilizamos Server Components para gerenciar o data fetching. Isso removeu a necessidade de passar dados por muitas camadas. Também criamos uma Data Access Layer. Isso garantiu que buscássemos os dados apenas uma vez por requisição.
Utilizamos Suspense e o hook use() para habilitar o HTML streaming. Isso exibe um skeleton screen enquanto os dados são carregados. O usuário visualiza a página mais rápido.
Os Desafios
Problema 1: HTTP 410 Gone Mecanismos de busca precisam de um status 410 quando uma página é removida permanentemente. O App Router não possui uma forma nativa de enviar isso. Resolvemos isso usando nosso servidor Express. O servidor intercepta a resposta e altera o código de status.
Problema 2: HTML Streaming Descobrimos que nossos skeleton screens de carregamento não apareciam. A página ficava em branco por segundos.
Descobrimos que o Nginx e o Akamai estavam fazendo o buffering de nossas respostas. Se o CDN faz o buffer do HTML, o streaming falha. Tivemos que desativar o buffering no Nginx e aplicar configurações personalizadas no Akamai. Assim que corrigimos isso, o conteúdo foi transmitido perfeitamente para o usuário.
O Rollout
Realizamos o rollout em duas fases para proteger nosso SEO.
Fase 1: Movemos o tráfego para o App Router, mas mantivemos o streaming desativado. Fizemos isso uma categoria por vez.
Fase 2: Habilitamos o HTML streaming. Testamos isso primeiro em categorias pequenas. Nossa equipe de SEO monitorou os rankings por duas semanas antes de passarmos para a próxima categoria.
Os Resultados
Os resultados foram enormes. Antes da migração, até 40% de nossas respostas eram lentas. Após a migração, as respostas lentas caíram 80%.
A maioria das páginas agora carrega em menos de 500ms.
Principais Aprendizados
- Use parallel routing para migrar sem interromper o desenvolvimento de novas funcionalidades.
- Uma camada de servidor personalizada ajuda você a controlar o tráfego e corrigir lacunas do framework.
- O streaming requer configuração em todas as camadas. Verifique o Nginx e seu CDN.
- Teste suas métricas de SEO durante o rollout.
Como reduzimos respostas lentas em 80% migrando para o Next.js App Router
A transição do Pages Router para o App Router foi uma das decisões mais impactantes que tomamos para melhorar a performance da nossa aplicação. Neste artigo, vou compartilhar como essa mudança nos permitiu reduzir o tempo de resposta em 80%.
O Problema: O peso do Pages Router
Com o Pages Router, enfrentávamos um desafio comum em aplicações React de grande escala: o tamanho do bundle de JavaScript.
Cada vez que um usuário acessava uma página, o navegador precisava baixar, processar e executar uma quantidade significativa de JavaScript para realizar a hidratação (hydration) da página. Isso resultava em:
- LCP (Largest Contentful Paint) alto: O conteúdo principal demorava a aparecer.
- TBT (Total Blocking Time) elevado: A página parecia travada enquanto o JavaScript era processado.
- Waterfalls de dados: Fazíamos buscas de dados em cascata, onde um componente esperava o outro terminar para começar sua própria busca.
A Solução: Next.js App Router
Ao migrar para o App Router, pudemos tirar proveito de três pilares fundamentais: Server Components, Streaming e um novo modelo de Caching.
1. Server Components
A maior mudança foi a adoção de Server Components. Diferente dos componentes tradicionais, os Server Components são renderizados inteiramente no servidor.
Isso significa que o JavaScript necessário para renderizar esses componentes não é enviado para o cliente. O resultado é um bundle muito menor e uma página que carrega quase instantaneamente.
// Exemplo de um Server Component buscando dados
async function UserProfile({ userId }) {
const res = await fetch(`https://api.example.com/user/${userId}`);
const user = await res.json();
return (
<div>
<h1>{user.name}</h1>
<p>{user.bio}</p>
</div>
);
}
2. Streaming e Suspense
Com o App Router, não precisamos mais esperar que toda a página seja gerada no servidor para começar a enviá-la ao cliente. Usando Streaming com o componente Suspense do React (ou o arquivo loading.js do Next.js), podemos enviar partes da interface conforme elas ficam prontas.
Isso melhora drasticamente a percepção de velocidade do usuário. Enquanto os dados pesados são buscados, o usuário já consegue interagir com o restante da página.
3. Caching Inteligente
O novo modelo de cache do Next.js é muito mais granular. Ele nos permite cachear requisições de dados de forma automática e eficiente, reduzindo a carga no nosso backend e acelerando as respostas.
Conclusão
A migração para o App Router não foi apenas uma atualização de versão; foi uma mudança de paradigma na forma como pensamos a arquitetura da nossa aplicação. Ao mover a lógica de busca de dados e a renderização para o servidor, conseguimos uma experiência de usuário muito mais fluida e rápida.
Os resultados foram claros: uma redução de 80% no tempo de resposta e uma melhora significativa em todas as métricas de performance.