Capítulo 120 de 456

loading.js

Core Idea

loading.js cria um Suspense boundary automático ao redor de page.js e filhos, mostrando um estado de loading instantâneo (prefetched) enquanto o conteúdo real do segmento carrega no servidor.

Key Concepts

  • Sem parâmetros: componentes loading.js não aceitam props.
  • Server Component por padrão: pode virar Client Component com 'use client'.
  • Escopo do wrap: loading.js envolve not-found.js, page.js e layout.js aninhados abaixo dele, mas NÃO envolve layout.js, template.js ou error.js do mesmo segmento.
  • Navegação prefetched e interrompível: o fallback é prefetchado, tornando a navegação imediata; trocar de rota não espera o conteúdo terminar de carregar; layouts compartilhados continuam interativos enquanto o novo segmento carrega.
  • Não cobre dado uncached do próprio layout: se o layout.js do mesmo segmento acessa cookies()/headers()/fetch uncached, loading.js não mostra fallback para isso (ver caveat em layout.js).
  • Status code sempre 200 durante streaming: erros como notFound()/redirect() dentro do streamed content não mudam o status HTTP já enviado; 404 real usa <meta name="robots" content="noindex"> na página streamada. Para status 404 de verdade (compliance/analytics), cheque a existência do recurso em proxy antes do body começar a ser streamado.

Code Examples

export default function Loading() {
  return <LoadingSkeleton />
}
  • O que demonstra: loading.js básico; automaticamente envolve page.js do mesmo diretório num <Suspense>.
import { Suspense } from 'react'
import { PostFeed, Weather } from './Components'

export default function Posts() {
  return (
    <section>
      <Suspense fallback={<p>Loading feed...</p>}>
        <PostFeed />
      </Suspense>
      <Suspense fallback={<p>Loading weather...</p>}>
        <Weather />
      </Suspense>
    </section>
  )
}
  • O que demonstra: Suspense boundaries manuais e granulares dentro da página, complementando o loading.js do segmento inteiro.

Reference Tables

Deployment OptionSupported
Node.js serverYes
Docker containerYes
Static exportNo
AdaptersPlatform-specific

Anti-patterns

  • Esperar loading.js cobrir dado runtime do layout.js: não cobre; sem Cache Components a navegação bloqueia até o layout terminar, com Cache Components é erro de build a menos que você envolva o acesso em <Suspense> próprio no layout.
  • Confiar no status HTTP para detectar 404 depois que o streaming começou: headers já foram enviados, status fica 200; use noindex (automático) ou valide antes do stream em proxy se precisa de 404 real.
  • Assumir que a resposta aparece imediatamente em qualquer browser: alguns browsers bufferizam resposta até 1024 bytes, afeta só apps triviais tipo "hello world".

Key Takeaways

  1. loading.js = Suspense automático por segmento; Suspense manual dentro da página = granularidade fina.
  2. Streaming começa quando um Suspense fallback renderiza ou um Server Component suspende; notFound() precisa vir antes desses pontos para ainda poder mudar o status code.
  3. Bots que só leem HTML estático (ex. Twitterbot) recebem generateMetadata já resolvido no <head> inicial; outros usam streaming metadata detectado por user agent.
  4. Streaming server-rendered não prejudica SEO.

Connects To

  • File-system conventions (ch111): índice das convenções.
  • layout.js (ch119): caveat compartilhado sobre dado runtime não coberto pelo loading.js.
  • error.js (ch114): outro boundary automático no mesmo nível de hierarquia, mas para erros em vez de loading.