Skip to content

fix(nuxt): preserve query parameters in payload extraction for cached routes#34751

Open
zowievangeest wants to merge 3 commits into
nuxt:mainfrom
zowievangeest:fix/payload-extraction-query-params
Open

fix(nuxt): preserve query parameters in payload extraction for cached routes#34751
zowievangeest wants to merge 3 commits into
nuxt:mainfrom
zowievangeest:fix/payload-extraction-query-params

Conversation

@zowievangeest
Copy link
Copy Markdown

🔗 Linked issue

Resolves #34496

📚 Description

When using routeRules with cache or isr/swr, payload extraction breaks for routes that depend on query parameters. For example, /items?id=1 and /items?id=2 both resolve to the same _payload.json, causing hydration mismatches because the client gets the wrong data.

It looks like this was introduced in #33467 which extended payload extraction to ISR/SWR cached routes, but the URL construction never accounted for query params.

Someone in the issue mentioned payloadExtraction: 'client' as a partial fix, but I can confirm it still doesn't work in 3.21.3. The server-side payload URL still strips query params regardless of that setting.

What I changed

The root cause is that the build hash was a bare unnamed query parameter (?abc123), making it impossible to tell apart from actual route query params. I introduced a named _b parameter instead, so the payload URL becomes /items/_payload.json?id=1&_b=abc123 rather than /items/_payload.json?abc123.

renderer.ts: Uses _b named param for the build hash. The isRenderingPayload handler now parses the URL properly with URLSearchParams.delete('_b') to reconstruct the original page URL with query params intact. Extracted a _buildPayloadURL helper to keep it clean.

payload.ts: Same _b approach on the client side for _getPayloadURL. Also added an early return in shouldLoadPayload for absolute URLs. The payload: true route rule from #33467 was causing it to try preloading payloads for full URLs like https://example.com/page from <NuxtLink> elements, which always failed.

Open question

I chose _b as the named parameter for the build hash since it's short and unlikely to collide with real query params, but I'm open to a different name or approach if the team has concerns about changing the payload URL format.

@bolt-new-by-stackblitz
Copy link
Copy Markdown

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@github-actions github-actions Bot added 5.x 🐛 bug Something isn't working as expected labels Mar 31, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 31, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d3c6d201-1670-4e03-b10f-c135b55cceb0

📥 Commits

Reviewing files that changed from the base of the PR and between dfce65b and c1cf967.

📒 Files selected for processing (1)
  • packages/nitro-server/src/runtime/handlers/renderer.ts

Walkthrough

Server renderer URL handling was changed to use the URL API to derive the base pathname and explicitly remove the _b query parameter while preserving other queries. Payload endpoint construction was refactored into a new module-local helper function _buildPayloadURL(ssrContext: NuxtSSRContext): string that composes the CDN/base path, pathname and _payload.json and sets _b=<buildId> via search params. Client composable _getPayloadURL now uses URL searchParams to apply the cache-busting _b query and shouldLoadPayload returns false for absolute URLs to skip cross-origin payload loading.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately describes the main change—fixing payload extraction to preserve query parameters in cached routes.
Description check ✅ Passed The description is well-detailed and directly related to the changeset, explaining the problem, root cause, and specific changes made.
Linked Issues check ✅ Passed The code changes directly address the requirement from #34496: payload extraction now preserves query parameters by using a named _b parameter for the build hash and reconstructing URLs properly.
Out of Scope Changes check ✅ Passed All changes in renderer.ts and payload.ts are directly scoped to fixing payload extraction with query parameters; no extraneous modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/nitro-server/src/runtime/handlers/renderer.ts`:
- Line 112: Remove the invalid assignment to event._path in renderer.ts and keep
only the valid request URL update: delete the expression assigning to
event._path (the left side "event._path") and retain the existing
event.node.req.url = routeUrl assignment so only the supported H3Event property
is updated; look for the statement that sets "event._path = event.node.req.url =
routeUrl" and change it to just "event.node.req.url = routeUrl".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 03af60e7-308f-4484-8b44-00b120e5f1a3

📥 Commits

Reviewing files that changed from the base of the PR and between 9f8be5f and dfce65b.

📒 Files selected for processing (2)
  • packages/nitro-server/src/runtime/handlers/renderer.ts
  • packages/nuxt/src/app/composables/payload.ts

Comment thread packages/nitro-server/src/runtime/handlers/renderer.ts Outdated
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Mar 31, 2026

Open in StackBlitz

@nuxt/kit

npm i https://pkg.pr.new/@nuxt/kit@34751

@nuxt/nitro-server

npm i https://pkg.pr.new/@nuxt/nitro-server@34751

nuxt

npm i https://pkg.pr.new/nuxt@34751

@nuxt/rspack-builder

npm i https://pkg.pr.new/@nuxt/rspack-builder@34751

@nuxt/schema

npm i https://pkg.pr.new/@nuxt/schema@34751

@nuxt/vite-builder

npm i https://pkg.pr.new/@nuxt/vite-builder@34751

@nuxt/webpack-builder

npm i https://pkg.pr.new/@nuxt/webpack-builder@34751

commit: c1cf967

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Mar 31, 2026

Merging this PR will improve performance by 11.55%

⚡ 1 improved benchmark
✅ 19 untouched benchmarks
⏩ 3 skipped benchmarks1

Performance Changes

Benchmark BASE HEAD Efficiency
loadNuxt in the basic test fixture 502.7 ms 450.7 ms +11.55%

Comparing zowievangeest:fix/payload-extraction-query-params (c1cf967) with main (8c078f4)2

Open in CodSpeed

Footnotes

  1. 3 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on main (9d4ce49) during the generation of this report, so 8c078f4 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

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

Labels

5.x 🐛 bug Something isn't working as expected

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Payload extraction ignores query parameters

1 participant