[PR #1091] [MERGED] fix(prerender): render layout-only parallel slot routes #1087

Closed
opened 2026-05-06 13:11:54 +02:00 by BreizhHardware · 0 comments

📋 Pull Request Information

Original PR: https://github.com/cloudflare/vinext/pull/1091
Author: @NathanDrake2406
Created: 5/6/2026
Status: Merged
Merged: 5/6/2026
Merged by: @james-elicx

Base: mainHead: nathan/fix-layout-only-prerender


📝 Commits (1)

  • 7deeed9 fix(prerender): render layout-only parallel slot routes

📊 Changes

4 files changed (+70 additions, -7 deletions)

View changed files

📝 packages/vinext/src/build/prerender.ts (+6 -5)
📝 packages/vinext/src/build/report.ts (+23 -1)
📝 tests/build-report.test.ts (+16 -1)
📝 tests/prerender.test.ts (+25 -0)

📄 Description

What this changes

Layout-only App Router routes that render through parallel slot content now participate in prerender and static export. Routes such as /parallel-nested/home, /parallel-nested/home/nested, and /slot-collision are rendered instead of being silently omitted from vinext-prerender.json and exported output.

Why

The prerender loop used route.pagePath as the only signal that an App Router route had renderable UI. That is too narrow for parallel routes: a segment can have layout.tsx with no page.tsx, while its visible content is supplied by a parallel slot page or default module.

Next.js models this differently:

Approach

Add a shared getAppRouteRenderEntryPath() helper that defines the App Router render-entry contract for build-time consumers:

  • children page.tsx remains the primary render entry
  • route handlers without UI remain API-only
  • layout-only UI routes fall back to the first parallel slot pagePath, then the first slot defaultPath

Both prerender collection and build-report classification use that helper, so route reporting and static generation agree on whether a route is renderable.

Validation

  • vp test run tests/prerender.test.ts
  • vp test run tests/build-report.test.ts
  • vp test run tests/routing.test.ts -t "layout routes whose own content is parallel slot pages|nested parallel slot sub-routes from layout-only parent"
  • vp test run tests/build-report.test.ts tests/prerender.test.ts tests/routing.test.ts -t "layout-only parallel-slot app routes|layout-only routes|layout routes whose own content is parallel slot pages|nested parallel slot sub-routes from layout-only parent"
  • vp check packages/vinext/src/build/prerender.ts packages/vinext/src/build/report.ts tests/prerender.test.ts tests/build-report.test.ts

Risks / follow-ups

This intentionally does not change route graph discovery or request-time rendering. It only fixes build-time route collection/classification for routes already discovered and renderable by the App Router runtime.

Closes #1052


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/cloudflare/vinext/pull/1091 **Author:** [@NathanDrake2406](https://github.com/NathanDrake2406) **Created:** 5/6/2026 **Status:** ✅ Merged **Merged:** 5/6/2026 **Merged by:** [@james-elicx](https://github.com/james-elicx) **Base:** `main` ← **Head:** `nathan/fix-layout-only-prerender` --- ### 📝 Commits (1) - [`7deeed9`](https://github.com/cloudflare/vinext/commit/7deeed9bc29fe64f20556ac6441466b3b38476ec) fix(prerender): render layout-only parallel slot routes ### 📊 Changes **4 files changed** (+70 additions, -7 deletions) <details> <summary>View changed files</summary> 📝 `packages/vinext/src/build/prerender.ts` (+6 -5) 📝 `packages/vinext/src/build/report.ts` (+23 -1) 📝 `tests/build-report.test.ts` (+16 -1) 📝 `tests/prerender.test.ts` (+25 -0) </details> ### 📄 Description ## What this changes Layout-only App Router routes that render through parallel slot content now participate in prerender and static export. Routes such as `/parallel-nested/home`, `/parallel-nested/home/nested`, and `/slot-collision` are rendered instead of being silently omitted from `vinext-prerender.json` and exported output. ## Why The prerender loop used `route.pagePath` as the only signal that an App Router route had renderable UI. That is too narrow for parallel routes: a segment can have `layout.tsx` with no `page.tsx`, while its visible content is supplied by a parallel slot page or default module. Next.js models this differently: - [`normalizeAppPath()` ignores `@slot` path segments when deriving the request path](https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/router/utils/app-paths.ts) - [`getLayoutOrPageModule()` can load a `defaultPage` as the page module for the default segment](https://github.com/vercel/next.js/blob/canary/packages/next/src/server/lib/app-dir-module.ts) - The relevant behavior is covered by the Next.js parallel routes test for nested parallel routes without a page component: [`parallel-routes-and-interception.test.ts`](https://github.com/vercel/next.js/blob/canary/test/e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts) ## Approach Add a shared `getAppRouteRenderEntryPath()` helper that defines the App Router render-entry contract for build-time consumers: - children `page.tsx` remains the primary render entry - route handlers without UI remain API-only - layout-only UI routes fall back to the first parallel slot `pagePath`, then the first slot `defaultPath` Both prerender collection and build-report classification use that helper, so route reporting and static generation agree on whether a route is renderable. ## Validation - `vp test run tests/prerender.test.ts` - `vp test run tests/build-report.test.ts` - `vp test run tests/routing.test.ts -t "layout routes whose own content is parallel slot pages|nested parallel slot sub-routes from layout-only parent"` - `vp test run tests/build-report.test.ts tests/prerender.test.ts tests/routing.test.ts -t "layout-only parallel-slot app routes|layout-only routes|layout routes whose own content is parallel slot pages|nested parallel slot sub-routes from layout-only parent"` - `vp check packages/vinext/src/build/prerender.ts packages/vinext/src/build/report.ts tests/prerender.test.ts tests/build-report.test.ts` ## Risks / follow-ups This intentionally does not change route graph discovery or request-time rendering. It only fixes build-time route collection/classification for routes already discovered and renderable by the App Router runtime. Closes #1052 --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
BreizhHardware 2026-05-06 13:11:54 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/vinext#1087
No description provided.