Skip to content

fix(shims): parse Pages data build IDs - #2806

Open
Boyeep wants to merge 4 commits into
cloudflare:mainfrom
Boyeep:fix/nexturl-data-build-id
Open

fix(shims): parse Pages data build IDs#2806
Boyeep wants to merge 4 commits into
cloudflare:mainfrom
Boyeep:fix/nexturl-data-build-id

Conversation

@Boyeep

@Boyeep Boyeep commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Summary

  • make NextURL.buildId represent the build ID encoded in a Pages Router /_next/data/ URL
  • parse and format data URLs across root pages, base paths, i18n, setters, and clones
  • preserve the raw data URL only when skipProxyUrlNormalize is enabled
  • pass URL-normalization config through Pages development, Node production, and Cloudflare Worker execution

User impact and reproduction

Before this change, an ordinary request such as / reported the running application's __VINEXT_BUILD_ID, even though the URL carried no data-request identity. Conversely, /_next/data/request-build/about.json did not expose request-build or the page pathname /about.

That breaks middleware and other code using request.nextUrl: ordinary page requests can be mistaken for data requests, while direct NextURL data URLs cannot be inspected, cloned, redirected, or rewritten with the identity encoded by the client request.

Expected Next.js behavior

Next derives buildId from the request URL. Its middleware adapter normally converts a Pages data request to the page URL and explicitly clears buildId before user middleware runs. With URL normalization disabled, middleware instead receives the raw data URL and its parsed build ID.

For localized root requests, the real client endpoint is /_next/data/<id>/en.json, as exercised by Next's middleware matcher E2E. Next's current standalone formatter can produce enindex.json after mutation; vinext deliberately preserves the real request endpoint instead.

Execution paths

  • Pages Router development: Vite middleware call in src/index.ts
  • Pages Router production: generated Pages server entry
  • Cloudflare Workers: the same generated Pages entry
  • App Router development/production: shared ordinary NextURL behavior is corrected; App Router has no Pages /_next/data/ endpoint

Tests and verification

Tests cover ordinary URLs, default middleware normalization with no build ID, raw skip-mode middleware URLs with a build ID, root and localized-root endpoints, base paths, locales, setters, cloning, and generated-entry wiring.

  • pnpm test tests/middleware-runtime.test.ts tests/pages-request-pipeline.test.ts tests/shims.test.ts — 1,407 passed
  • pnpm exec vp check tests/middleware-runtime.test.ts tests/pages-request-pipeline.test.ts tests/shims.test.ts — passed
  • prior targeted entry-template/data-route checks and vinext#build — passed

Self-review

Automated review found that the first implementation could prefix a preserved raw path twice. Commit e2d52bd3 fixed that and added regression coverage for href, toString(), middleware use, and clone().

A second full review clarified the default middleware contract, added end-to-end pipeline proof that default mode receives the page URL with no build ID, and documented/tested the localized-root endpoint divergence. No broader parser-sharing refactor was taken because request analysis and current-build validation have different responsibilities.

@pkg-pr-new

pkg-pr-new Bot commented Aug 4, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@vinext/cloudflare@2806
npm i https://pkg.pr.new/create-vinext-app@2806
npm i https://pkg.pr.new/@vinext/types@2806
npm i https://pkg.pr.new/vinext@2806

commit: 4c655af

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4c655af23a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


const paths = pathname.slice("/_next/data/".length, -".json".length).split("/");
this._buildId = paths[0];
const nextDataPathname = paths[1] !== "index" ? `/${paths.slice(1).join("/")}` : "/";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve index-prefixed routes when parsing data URLs

When a valid Pages route starts with /index, buildPagesDataPath intentionally adds an extra index/ prefix, so /index/foo becomes /_next/data/id/index/index/foo.json. This condition treats every first post-build segment named index as the root, causing that URL's NextURL.pathname to become / and its formatted href or clone to address the root endpoint instead of /index/foo. Only an exact remaining path of index should map to /; apply the same index-prefix denormalization already implemented by parseNextDataPathname.

AGENTS.md reference: AGENTS.md:L174-L178

Useful? React with 👍 / 👎.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Performance benchmarks

Compared 4c655af against base dfc979c using alternating same-runner rounds. Next.js was unchanged and skipped.

0 improved · 0 regressed · 6 within ±1.5%

Scenario Framework Baseline Current Change
Client bundle size (gzip) vinext 134.6 KB 134.6 KB ⚫ +0.0%
Client entry size (gzip) vinext 122.2 KB 122.1 KB ⚫ -0.0%
Dev server cold start vinext 2.97 s 2.94 s ⚫ -0.9%
Production build time vinext 3.23 s 3.26 s ⚫ +1.0%
RSC entry closure size (gzip) vinext 113.8 KB 113.8 KB ⚫ -0.0%
Server bundle size (gzip) vinext 191.3 KB 191.6 KB ⚫ +0.1%

View detailed results and traces

🟢 improvement · 🔴 regression · ⚫ change below 1.5% · paired base/head

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant