fix(pages-router): run instrumentation-client.ts before hydration (#1474)#1671
fix(pages-router): run instrumentation-client.ts before hydration (#1474)#1671james-elicx wants to merge 1 commit into
Conversation
|
/bigbonk review |
commit: |
|
There was a problem hiding this comment.
Review: LGTM
Small, focused fix with good test coverage — approving.
What this does
Adds an explicit side-effect import of the user's instrumentation-client.{ts,js} at the very top of the generated Pages Router client entry, before vinext/instrumentation-client and before hydrateRoot(). This matches Next.js's page-bootstrap.ts ordering where require-instrumentation-client is the first import.
What I checked
- Correctness: Bare side-effect import (
import "…";) ensures top-level statements execute unconditionally.JSON.stringify+normalizePathSeparatorshandles path escaping and Windows separators correctly. - Import ordering: The user file import precedes all other imports including
vinext/instrumentation-client, matching Next.js's contract. - Backward compatibility: Default parameter
instrumentationClientPath: string | null = nullmeans existing callers are unaffected. - Wiring in index.ts:
instrumentationClientPathis already resolved at line 1085 viafindInstrumentationClientFile()— the one-line change at line 722 is clean plumbing. - Test coverage: Both the presence case (import appears before
hydrateRoot() and absence case (no spurious import when file doesn't exist) are verified. Tests follow the existing tmpDir/try-finally pattern. - Comment quality: The inline block comment (lines 47-60) explains why the explicit import is needed (tree-shaker safety for indirect loads) and cites the Next.js source.
Nit (non-blocking)
When instrumentationClientPath is null, userInstrumentationImport is "", so the template produces a leading blank line (\nimport "vinext/instrumentation-client";). Cosmetic and harmless for a virtual module, but if you want to clean it up:
const userInstrumentationImport = instrumentationClientPath
? `import ${JSON.stringify(normalizePathSeparators(instrumentationClientPath))};\n`
: "";
return `${userInstrumentationImport}import "vinext/instrumentation-client";(i.e., drop the newline after the interpolation in the template literal). Totally optional.
|
Review posted on PR #1671. Here's the summary: Approved. The change is small, correct, and well-tested.
|
) The generated Pages Router client entry imported `vinext/instrumentation-client` which transitively loads the user's `instrumentation-client.ts` via the `private-next-instrumentation-client` alias. That indirection left the contract implicit and the side effects vulnerable to aggressive tree-shaking. Side-effect-import the user's file directly from the generated client entry when it exists, ahead of `hydrateRoot()`. Mirrors Next.js's `page-bootstrap.ts`, which side-effect-imports `require-instrumentation-client` before `initialize`/`hydrate`. Adds focused unit tests in `tests/entry-templates.test.ts` asserting that the generated client entry imports the user's `instrumentation-client.ts` before `hydrateRoot(` is called, and that nothing spurious is emitted when no file is present. Refs #1474.
b333a46 to
7fe0338
Compare
|
Rebased on origin/main. Main added an |
Summary
instrumentation-client.{ts,js}from the generated Pages Router client entry, beforehydrateRoot(). Previously the contract was implicit (transitive load viaprivate-next-instrumentation-client), which left the user's top-level statements vulnerable to tree-shaking and ordering surprises.page-bootstrap.ts, which side-effect-importsrequire-instrumentation-clientbeforeinitialize/hydrate(.nextjs-ref/packages/next/src/client/page-bootstrap.tsL1).tests/entry-templates.test.ts:instrumentation-client.tsand that import precedeshydrateRoot(.Closes #1474 once CI passes.
Test plan
pnpm test tests/entry-templates.test.ts tests/pages-router.test.ts tests/instrumentation.test.ts— 320 tests pass locally.pnpm run checkclean.tests/e2e/pages-router/instrumentation-client.spec.ts).