mirror of
https://github.com/cloudflare/vinext.git
synced 2026-09-14 19:04:59 +08:00
33be48648d
## Summary - Register `beforeInteractive` Scripts with `src` through BeforeInteractiveContext so they are hoisted into <head> ahead of interactive, exactly like the inline form (previously they bypassed the registry and rendered in source order, after React Float's head content). - Suppress the client React render for both inline AND src beforeInteractive Scripts in the App Router so the hoisted tag is never duplicated. - Tag every hoisted script with Next.js's `data-nscript="beforeInteractive"` marker. - Map `crossOrigin` -> `crossorigin` and `referrerPolicy` -> `referrerpolicy` on hoisted scripts (parity with Next.js set-attributes-from-props). - Extract `renderBeforeInteractiveInlineScripts` into a dedicated, pure module (before-interactive-head.ts) so the emit path is unit-testable. ## Root Cause The beforeInteractive SSR branch computed `inlineContent = src ? null : ...` and only registered when `inlineContent !== null`, so any Script with a `src` was never captured by the registry and never spliced into <head>; it stayed where the user wrote it, behind React Float's hoisted resource hints, defeating the before-interactive guarantee. Hoisting src scripts then requires the client to stop rendering them through React (the React-created <script> never executes and would only add a duplicate DOM node), so the client dedupe condition is aligned with the SSR registration condition. The hoisted output also lacked Next.js's `data-nscript` marker, and REACT_TO_HTML_ATTR omitted crossOrigin/referrerPolicy, so those attribute names did not match Next.js's lowercased output. ## References - Fixes #2016 - Next.js: .nextjs-ref/packages/next/src/client/script.tsx (data-nscript, src/inline registry parity), set-attributes-from-props.ts (lowercased attrs) - Ported: test/e2e/app-dir/script-before-interactive/script-before-interactive.test.ts ## Verification - CI=true pnpm test tests/script.test.ts tests/script-head-ordering.test.ts tests/nextjs-compat/script-nonce.test.ts tests/shims.test.ts -> 1139 passed - CI=true npx vp check on all changed files -> pass Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
60 lines
986 B
Plaintext
60 lines
986 B
Plaintext
node_modules/
|
|
dist/
|
|
out/
|
|
*.tsbuildinfo
|
|
.vite/
|
|
.turbo/
|
|
.ecosystem-test/
|
|
.next/
|
|
.wrangler/
|
|
test-results/
|
|
playwright-report/
|
|
out-e2e
|
|
|
|
# Environment + secrets
|
|
.env
|
|
.env.*
|
|
!.env.example
|
|
# wrangler convention for local-only secrets passed to `wrangler dev`
|
|
.dev.vars
|
|
.dev.vars.*
|
|
|
|
# Logs / coverage
|
|
*.log
|
|
npm-debug.log*
|
|
yarn-debug.log*
|
|
yarn-error.log*
|
|
pnpm-debug.log*
|
|
coverage/
|
|
reports/
|
|
|
|
# Worktrees
|
|
.worktrees/
|
|
.claude
|
|
|
|
# Next.js reference clone (for searching source/tests)
|
|
.nextjs-ref/
|
|
|
|
# OS / editor
|
|
.DS_Store
|
|
.idea/
|
|
.vscode/
|
|
.claude/
|
|
.codex/
|
|
|
|
# Nix
|
|
result
|
|
result-*
|
|
# The Nix `result` pattern above also matches Next.js compat fixture routes
|
|
# named `result`; re-include them so they don't silently fall out of tracking.
|
|
!tests/fixtures/root-layout-redirect/app/result/
|
|
.direnv/
|
|
.corepack/
|
|
|
|
.vinext
|
|
next-env.d.ts
|
|
|
|
# Leaked temp fixtures from the oxlint prefer-shared-utils rule test
|
|
# (normally cleaned up in afterEach; ignore so a crashed run can't commit them).
|
|
__lint_rule_fixtures__-*
|