Capítulo 117 de 456

instrumentation-client.js

Core Idea

instrumentation-client.js|ts (raiz do projeto ou src/) roda código client-side (monitoring, analytics, polyfills) que executa após o HTML carregar mas antes da hidratação React começar, sem precisar exportar função específica.

Key Concepts

  • Sem export obrigatório: diferente da versão server, pode escrever código de monitoramento direto no top-level do arquivo.
  • onRouterTransitionStart(url, navigationType, event?): hook opcional para observar início de navegações do App Router; navigationType é 'push' | 'replace' | 'traverse'; erros dentro do hook são isolados e não afetam a navegação.
  • event (experimental): requer experimental.instrumentationClientRouterTransitionEvents: true em next.config.ts; traz id, timestamp, fromRoutes (rotas visíveis antes da navegação, formato filesystem como /blog/[slug]), prefetchIntent ('full' | 'auto' | 'none' | null).
  • Execution timing: depois do HTML carregado, antes da hidratação React, antes de qualquer interação do usuário. Só código síncrono top-level tem garantia de rodar antes da hidratação; Promise/import()/top-level await são fire-and-forget e podem resolver depois da hidratação já ter começado.
  • instrumentationClientInject: opção de next.config.js para plugins (ex. withSentry) injetarem seu próprio módulo de instrumentação client, executando antes deste arquivo, em ordem de array.

Code Examples

export function onRouterTransitionStart(
  url: string,
  navigationType: 'push' | 'replace' | 'traverse'
) {
  console.log(url, navigationType)
}
  • O que demonstra: hook básico de rastreamento de navegação, sem o event experimental.
import ResizeObserverPolyfill from './lib/polyfills/resize-observer'

if (!window.ResizeObserver) {
  window.ResizeObserver = ResizeObserverPolyfill
}
  • O que demonstra: polyfill garantido antes da hidratação via import estático + aplicação síncrona (import dinâmico condicional não teria essa garantia).

Anti-patterns

  • Usar import() condicional para polyfill crítico: é fire-and-forget, pode aplicar depois da hidratação já ter começado, tarde demais para os componentes; use import estático + checagem síncrona.
  • Código pesado/bloqueante no arquivo: Next.js loga warning em dev se a inicialização passar de 16ms, pode atrasar o carregamento da página.
  • Não isolar erros de tracking com try-catch: uma falha de monitoramento pode afetar outras features de instrumentação se não isolada.
  • Assumir prefetchIntent sempre presente: é null em navegações programáticas (router.push()) ou back/forward do browser, sem link associado.

Key Takeaways

  1. Diferente do instrumentation.js (server), este arquivo não precisa de export register, o próprio corpo do arquivo já executa.
  2. Next.js já injeta polyfills baseline (fetch, URL, Object.assign); só adicione polyfill para o que estiver fora dessa baseline.
  3. onRouterTransitionStart é o ponto certo para analytics de navegação client-side (page views, breadcrumbs de erro).
  4. Plugins de terceiros (Sentry etc.) podem injetar módulo próprio via instrumentationClientInject, executando antes do arquivo da aplicação.

Connects To

  • File-system conventions (ch111): índice das convenções.
  • instrumentation.js (ch116): contraparte server-side, com register/onRequestError.