Skip to content

Commit

Permalink
backport: fix prerender issue with intercepting routes + generateStat…
Browse files Browse the repository at this point in the history
…icParams (#75170)

Backports the testcase added in
#75167 in
[9bf61bc](9bf61bc).

Confirmed failure via [this
run](https://github.com/vercel/next.js/actions/runs/12898849331/job/35966678688?pr=75170)

Adds the fix in
[0ab1e32](0ab1e32).
This change is identical to the code used in canary, which was added as
part of the `rootParams` feature via
#73816
([ref](https://github.com/vercel/next.js/blob/d12e2e82b778eef8393f47944a258a55c6c508fe/packages/next/src/build/static-paths/app.ts#L316-L317))

This regression was caused by `segments` containing all possible
segments (including parallel routes), not just the page segment. As a
result, `paramKeys` was incorrectly being calculated. We don't need to
traverse the segments to determine the param keys: we have the route
regex & matcher, it's more reliable to extract it from that.
  • Loading branch information
ztanner authored Jan 22, 2025
1 parent 819d575 commit 7099753
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 14 deletions.
16 changes: 3 additions & 13 deletions packages/next/src/build/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1289,18 +1289,8 @@ export async function buildAppStaticPaths({
minimalMode: ciEnvironment.hasNextSupport,
})

const paramKeys = new Set<string>()

const staticParamKeys = new Set<string>()
for (const segment of segments) {
if (segment.param) {
paramKeys.add(segment.param)

if (segment.config?.dynamicParams === false) {
staticParamKeys.add(segment.param)
}
}
}
const regex = getRouteRegex(page)
const paramKeys = Object.keys(getRouteMatcher(regex)(page) || {})

const afterRunner = new AfterRunner()

Expand Down Expand Up @@ -1417,7 +1407,7 @@ export async function buildAppStaticPaths({
// Determine if all the segments have had their parameters provided. If there
// was no dynamic parameters, then we've collected all the params.
const hadAllParamsGenerated =
paramKeys.size === 0 ||
paramKeys.length === 0 ||
(routeParams.length > 0 &&
routeParams.every((params) => {
for (const key of paramKeys) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function CatchAll() {
return null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Page() {
return 'intercepted'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
type Props = {
params: Promise<{ slug: string }>
}

export default async function Page({ params }: Props) {
const { slug } = await params
return <div>Hello {slug}</div>
}

export function generateStaticParams() {
return [
{ slug: 'a' },
{ slug: 'b' },
{ slug: 'c' },
{ slug: 'd' },
{ slug: 'e' },
{ slug: 'f' },
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils'

describe('interception-dynamic-segment', () => {
const { next } = nextTestSetup({
const { next, isNextStart } = nextTestSetup({
files: __dirname,
})

Expand All @@ -15,4 +15,13 @@ describe('interception-dynamic-segment', () => {
await check(() => browser.elementById('modal').text(), '')
await check(() => browser.elementById('children').text(), /not intercepted/)
})

if (isNextStart) {
it('should correctly prerender segments with generateStaticParams', async () => {
expect(next.cliOutput).toContain('/generate-static-params/a')
const res = await next.fetch('/generate-static-params/a')
expect(res.status).toBe(200)
expect(res.headers.get('x-nextjs-cache')).toBe('HIT')
})
}
})

0 comments on commit 7099753

Please sign in to comment.