Skip to content

[dynamicIO] Split up static generation into two phases #79629

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: canary
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/next/src/build/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,7 @@ const staticWorkerExposedMethods = [
'getDefinedNamedExports',
'exportPages',
] as const
type StaticWorker = typeof import('./worker') & Worker
export type StaticWorker = typeof import('./worker') & Worker
export function createStaticWorker(
config: NextConfigComplete,
options: {
Expand Down
31 changes: 16 additions & 15 deletions packages/next/src/build/static-paths/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ export async function buildAppStaticPaths({
isRoutePPREnabled: boolean
buildId: string
rootParamKeys: readonly string[]
}): Promise<Partial<StaticPathsResult>> {
}): Promise<StaticPathsResult> {
if (
segments.some((generate) => generate.config?.dynamicParams === true) &&
nextConfigOutput === 'export'
Expand Down Expand Up @@ -484,12 +484,7 @@ export async function buildAppStaticPaths({
: undefined
: FallbackMode.NOT_FOUND

const result: Partial<StaticPathsResult> = {
fallbackMode,
prerenderedRoutes: lastDynamicSegmentHadGenerateStaticParams
? []
: undefined,
}
const prerenderedRoutesByPathname = new Map<string, PrerenderedRoute>()

if (hadAllParamsGenerated || isRoutePPREnabled) {
if (isRoutePPREnabled) {
Expand All @@ -499,8 +494,7 @@ export async function buildAppStaticPaths({
...filterUniqueRootParamsCombinations(rootParamKeys, routeParams)
)

result.prerenderedRoutes ??= []
result.prerenderedRoutes.push({
prerenderedRoutesByPathname.set(page, {
params: {},
pathname: page,
encodedPathname: page,
Expand Down Expand Up @@ -577,10 +571,11 @@ export async function buildAppStaticPaths({
fallbackRouteParams.includes(param)
)

result.prerenderedRoutes ??= []
result.prerenderedRoutes.push({
pathname = normalizePathname(pathname)

prerenderedRoutesByPathname.set(pathname, {
params,
pathname: normalizePathname(pathname),
pathname,
encodedPathname: normalizePathname(encodedPathname),
fallbackRouteParams,
fallbackMode: dynamicParams
Expand All @@ -597,10 +592,16 @@ export async function buildAppStaticPaths({
})
}

const prerenderedRoutes =
prerenderedRoutesByPathname.size > 0 ||
lastDynamicSegmentHadGenerateStaticParams
? [...prerenderedRoutesByPathname.values()]
: undefined

// Now we have to set the throwOnEmptyStaticShell for each of the routes.
if (result.prerenderedRoutes && dynamicIO) {
assignErrorIfEmpty(result.prerenderedRoutes, routeParamKeys)
if (prerenderedRoutes && dynamicIO) {
assignErrorIfEmpty(prerenderedRoutes, routeParamKeys)
}

return result
return { fallbackMode, prerenderedRoutes }
}
80 changes: 39 additions & 41 deletions packages/next/src/build/static-paths/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export async function buildPagesStaticPaths({
locales?: readonly string[]
defaultLocale?: string
}): Promise<StaticPathsResult> {
const prerenderedRoutes: PrerenderedRoute[] = []
const prerenderedRoutesByPathname = new Map<string, PrerenderedRoute>()
const _routeRegex = getRouteRegex(page)
const _routeMatcher = getRouteMatcher(_routeRegex)

Expand Down Expand Up @@ -108,20 +108,24 @@ export async function buildPagesStaticPaths({
// If leveraging the string paths variant the entry should already be
// encoded so we decode the segments ensuring we only escape path
// delimiters
prerenderedRoutes.push({
params,
pathname: entry
.split('/')
.map((segment) =>
escapePathDelimiters(decodeURIComponent(segment), true)
)
.join('/'),
encodedPathname: entry,
fallbackRouteParams: undefined,
fallbackMode: parseStaticPathsResult(staticPathsResult.fallback),
fallbackRootParams: undefined,
throwOnEmptyStaticShell: undefined,
})
const pathname = entry
.split('/')
.map((segment) =>
escapePathDelimiters(decodeURIComponent(segment), true)
)
.join('/')

if (!prerenderedRoutesByPathname.has(pathname)) {
prerenderedRoutesByPathname.set(pathname, {
params,
pathname,
encodedPathname: entry,
fallbackRouteParams: undefined,
fallbackMode: parseStaticPathsResult(staticPathsResult.fallback),
fallbackRootParams: undefined,
throwOnEmptyStaticShell: undefined,
})
}
}
// For the object-provided path, we must make sure it specifies all
// required keys.
Expand Down Expand Up @@ -197,36 +201,30 @@ export async function buildPagesStaticPaths({
}
const curLocale = entry.locale || defaultLocale || ''

prerenderedRoutes.push({
params,
pathname: normalizePathname(
`${curLocale ? `/${curLocale}` : ''}${
curLocale && builtPage === '/' ? '' : builtPage
}`
),
encodedPathname: normalizePathname(
`${curLocale ? `/${curLocale}` : ''}${
curLocale && encodedBuiltPage === '/' ? '' : encodedBuiltPage
}`
),
fallbackRouteParams: undefined,
fallbackMode: parseStaticPathsResult(staticPathsResult.fallback),
fallbackRootParams: undefined,
throwOnEmptyStaticShell: undefined,
})
const pathname = normalizePathname(
`${curLocale ? `/${curLocale}` : ''}${curLocale && builtPage === '/' ? '' : builtPage}`
)

if (!prerenderedRoutesByPathname.has(pathname)) {
prerenderedRoutesByPathname.set(pathname, {
params,
pathname,
encodedPathname: normalizePathname(
`${curLocale ? `/${curLocale}` : ''}${
curLocale && encodedBuiltPage === '/' ? '' : encodedBuiltPage
}`
),
fallbackRouteParams: undefined,
fallbackMode: parseStaticPathsResult(staticPathsResult.fallback),
fallbackRootParams: undefined,
throwOnEmptyStaticShell: undefined,
})
}
}
})

const seen = new Set<string>()

return {
fallbackMode: parseStaticPathsResult(staticPathsResult.fallback),
prerenderedRoutes: prerenderedRoutes.filter((route) => {
if (seen.has(route.pathname)) return false

// Filter out duplicate paths.
seen.add(route.pathname)
return true
}),
prerenderedRoutes: [...prerenderedRoutesByPathname.values()],
}
}
4 changes: 2 additions & 2 deletions packages/next/src/build/static-paths/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ type FallbackPrerenderedRoute = {
export type PrerenderedRoute = StaticPrerenderedRoute | FallbackPrerenderedRoute

export type StaticPathsResult = {
fallbackMode: FallbackMode
prerenderedRoutes: PrerenderedRoute[]
fallbackMode: FallbackMode | undefined
prerenderedRoutes: PrerenderedRoute[] | undefined
}
Loading
Loading