mirror of
https://github.com/hanzoai/next.js.git
synced 2026-10-30 14:46:38 +00:00
## Stack Position (2/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) Parent: #94755 Next: #94756 ## What This PR Does Adds an experimental third argument to the existing start hook: ```ts export function onRouterTransitionStart(url, navigationType, event) {} ``` The event contains: - `id` and framework-captured Unix `timestamp` in milliseconds - `fromRoutes`: route patterns visible when navigation is dispatched - `prefetchIntent`: `full`, `auto`, or `none` The primary `children` route is first, followed by visible parallel slots in deterministic order. ## Design Start owns the context that is authoritative before navigation work begins: the screen being left and the caller's prefetch intent. Destination routes and the cache result actually used are reported by commit instead. Consumers correlate them by transition ID. Without `experimental.instrumentationClientRouterTransitionEvents`, the existing two-argument hook behavior is unchanged. ## Not In This PR - Destination routes or observed prefetch result - Commit, abort, mismatch, or settled hooks ## Reviewer Focus - Route pattern extraction, including dynamic and parallel routes - Primary route ordering - Link intent propagation and experimental gating ## Validation - `pnpm build-all` - `pnpm --filter=next build` - App Router instrumentation client E2E: 15/15 <!-- NEXT_JS_LLM_PR --> --------- Co-authored-by: Jude Gao <[email protected]>
53 lines
1.9 KiB
TypeScript
53 lines
1.9 KiB
TypeScript
import { nextTestSetup } from 'e2e-utils'
|
|
|
|
// The router transition instrumentation only emits the rich transition event
|
|
// (which carries `fromRoutes`) when the experimental flag is enabled. That code
|
|
// path is gated behind `process.env.__NEXT_INSTRUMENTATION_CLIENT_ROUTER_TRANSITION_EVENTS`,
|
|
// which is replaced with a literal at build time so the disabled path can be
|
|
// dead-code-eliminated. `fromRoutes` is the marker: in client runtime code it
|
|
// appears only inside that gated branch, and object keys survive minification.
|
|
describe('instrumentation client router transition events - dead code elimination', () => {
|
|
describe('when the experimental flag is enabled', () => {
|
|
const { next, skipped } = nextTestSetup({
|
|
files: __dirname,
|
|
nextConfig: {
|
|
experimental: { instrumentationClientRouterTransitionEvents: true },
|
|
},
|
|
})
|
|
if (skipped) return
|
|
|
|
it('keeps the transition event payload in the client bundle', async () => {
|
|
const $ = await next.render$('/')
|
|
const chunkContents = await Promise.all(
|
|
$('script[src]')
|
|
.toArray()
|
|
.map((el) => next.fetch($(el).attr('src')).then((res) => res.text()))
|
|
)
|
|
|
|
expect(
|
|
chunkContents.some((content) => content.includes('fromRoutes'))
|
|
).toBe(true)
|
|
})
|
|
})
|
|
|
|
describe('when the experimental flag is disabled', () => {
|
|
const { next, skipped } = nextTestSetup({
|
|
files: __dirname,
|
|
})
|
|
if (skipped) return
|
|
|
|
it('removes the transition event payload from the client bundle', async () => {
|
|
const $ = await next.render$('/')
|
|
const chunkContents = await Promise.all(
|
|
$('script[src]')
|
|
.toArray()
|
|
.map((el) => next.fetch($(el).attr('src')).then((res) => res.text()))
|
|
)
|
|
|
|
expect(
|
|
chunkContents.some((content) => content.includes('fromRoutes'))
|
|
).toBe(false)
|
|
})
|
|
})
|
|
})
|