stamatios
← Voltar ao feed
Esteira fatiando bloco de código em peças de quebra-cabeça de tamanhos variados, chunking do Turbopack no Next.js
Dev & Engenharia

Turbopack explica como divide seu JavaScript em chunks

resumo de ~3 min

O problema do chunking

Ao abrir o site do Next.js, a aba de rede mostra dezenas de arquivos JavaScript com nomes aparentemente aleatórios: são os chunks gerados pelo Turbopack, que contêm o código da aplicação, as dependências e o runtime que conecta tudo. "Chunking" é o processo de decidir qual código vai em qual arquivo, e cada estratégia tem compromissos distintos.

A abordagem mais simples é um único chunk com todo o JavaScript do app: no exemplo do artigo, 355 módulos em 1,09 MB carregados em toda página. A navegação fica rápida porque toda carga seguinte é um acerto de cache, mas páginas com pouco JavaScript ainda baixam código de todas as outras, e o site fica cada vez mais pesado.

Um chunk por página resolve o excesso de código, mas quebra o cache: se toda página usa um <Footer />, o código dele é duplicado em cada chunk, e um visitante de quatro páginas baixa o mesmo rodapé quatro vezes. Um chunk por módulo eliminaria duplicação, mas geraria centenas de requisições pequenas - e, mesmo com HTTP/2, cada requisição carrega overhead, e compactadores como gzip funcionam pior com muitos arquivos pequenos (dicionários de compressão ajudam, mas não resolvem).

Menos requisições ou menos código

O dilema central: minimizar o tamanho baixado e o número de requisições são objetivos que conflitam. Chunks maiores reduzem requisições, mas são menos reutilizáveis entre páginas.

A solução do Turbopack é mesclar chunks menores em maiores, usando o conceito de chunk group: a coleção de chunks carregados juntos, como todos os chunks de /home. O Turbopack só mescla chunks do mesmo grupo, o que garante que a mesclagem não adiciona nada que a página já baixaria.

Para decidir quando mesclar vale a pena, o algoritmo analisa cenários de navegação. Usando os chunks A (<Footer />, usado em toda página) e B (<VideoPlayer />, só na home): se o visitante carrega a home e sai, mesclar sempre compensa. Se navega para uma página que precisa só de A, o arquivo mesclado é inútil ali e A é baixado de novo. A mesclagem só compensa entre navegações quando ambas as páginas precisam dos dois chunks. O Turbopack conta quantos grupos usam só A, só B ou A+B, pondera cada cenário por probabilidade e estima que 2/3 das sessões visitam uma única página e 1/3 envolvem duas ou mais.

Comparação de estratégias

O autor mediu nextjs.org com três configurações: sem mesclagem (561,6 KiB em 96 requisições), os padrões do Turbopack (554,8 KiB em 38) e mesclagem máxima por grupo (610,0 KiB em 15). Os padrões cortaram as requisições pela metade sem aumentar o código; a mesclagem máxima reduziu ainda mais as requisições, mas enviou 10% mais código no total - e teria sido melhor se a navegação fosse mais curta.

Novidades do Next.js 16.3

Duas limitações motivam os novos recursos: a mesclagem é decidida em tempo de build, sem saber o que o navegador já tem em cache, e o algoritmo chuta como as pessoas navegam.

  • Busca de chunks mais inteligente: com experimental.turbopackChunking.generateComponentChunks, o Turbopack emite versões não mescladas junto das mescladas e, em tempo de requisição, escolhe a opção mais barata - o chunk mesclado ou só as partes faltantes. Experimentos com a diretiva only-if-cached podem estender isso a visitas de retorno.
  • Chunking baseado em analytics: novas chaves em experimental.turbopackChunking permitem ajustar as suposições: firstPageLoadPriority (peso entre sessões de uma e duas páginas, padrão 0,67; taxa de rejeição é um bom ponto de partida), priorityRoutes (páginas prioritárias, mescladas mais oportunisticamente) e clusters (grupos de rotas visitadas em conjunto, definidos por expressões regulares).
  • Chunks menores e menos numerosos: tree-shaking de módulos CJS (antes só ESM), via experimental.turbopackCjsTreeShaking; um runtime compartilhado (experimental.turbopackSharedRuntime) que economiza uma requisição bloqueante e cerca de 10 KB por navegação após a primeira; e um runtime padrão mais leve, sem código de WebAssembly e Web Worker, inserido só quando detectado.

Os recursos estão disponíveis no Next.js 16.3 ou posterior; alguns serão padrão em versões futuras.