next.js
8b57e82a - router instrumentation: refactor client hook dispatch (1/7) (#94755)

Commit
106 days ago
router instrumentation: refactor client hook dispatch (1/7) (#94755) ## Stack Position (1/7) in the router instrumentation stack. 1. **#94755: router instrumentation: refactor client hook dispatch (1/7)** 2. #94766: router instrumentation: add transition start context (2/7) 3. #94756: router instrumentation: add transition commit events (3/7) 4. #94765: router instrumentation: add commit route and prefetch context (4/7) 5. #94757: router instrumentation: add transition abort events (5/7) 6. #94758: router instrumentation: add route mismatch events (6/7) 7. #94737: router instrumentation: add transition settlement events (7/7) ## What This PR Does Refactors client instrumentation loading so webpack and Turbopack provide an ordered array of instrumentation modules to a shared router-transition dispatcher. The existing config remains unchanged: ```ts const nextConfig = { instrumentationClientInject: ['my-observability-library/client'], } ``` ## Motivation This refactor lands first, ahead of the new lifecycle events, for two reasons: 1. **Maintainability — the stack adds more hooks.** Previously the hook fan-out was generated at build time (a composed `onRouterTransitionStart` emitted by both the webpack loader and the Turbopack import map). Each new event (commit, settled, abort, mismatch) would require regenerating that composition in both bundlers, per hook. Moving dispatch into one runtime module means new hooks are added once, in a single place, with no new bundler composition logic per hook. 2. **Fault tolerance.** Dispatch now isolates failures across instrumentation modules: - A hook that throws is caught per module, so the remaining modules still run for that navigation (previously, one throwing hook aborted the rest). - Modules whose exports are `null`/`undefined` (side-effect-only) are filtered out instead of throwing (previously an unguarded existence check could throw a `TypeError` and break hydration). ## Design - Injected modules run in array order before the application instrumentation file. - With no injected modules, bundlers preserve the direct user instrumentation alias and the runtime normalizes it to a one-element array. - Hooks are read from each module at dispatch time. - A failing hook does not prevent later modules from running. - Side-effect-only modules may export `null` or `undefined`. - The dispatcher can support additional hooks without generating new bundler composition logic for each hook. ## Not In This PR - New event arguments or lifecycle hooks - Transition IDs, timestamps, route data, or prefetch data ## Reviewer Focus - Webpack and Turbopack produce the same ordered module array. - Hook fan-out stays in the router-transition dispatcher. - Ordering, dynamic hook lookup, and per-module error isolation are preserved. ## Validation - `pnpm --filter=next types` - `cargo fmt --all -- --check` - Instrumentation client E2E coverage in dev and production with webpack and Turbopack - Cache Components instrumentation client coverage <!-- NEXT_JS_LLM_PR --> Co-authored-by: Jude Gao <jude.gao@vercel.com>
Author
Parents
Loading