Skip to content

Commit

Permalink
refactor: cleanup page infos implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
wyattjoh committed Dec 9, 2023
1 parent 1f6defd commit 7b5a465
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 90 deletions.
10 changes: 4 additions & 6 deletions packages/next/src/build/collect-build-traces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {

import path from 'path'
import fs from 'fs/promises'
import type { PageInfo } from './utils'
import type { PageInfo } from './page-info'
import { loadBindings } from './swc'
import { nonNullable } from '../lib/non-nullable'
import * as ciEnvironment from '../telemetry/ci-info'
Expand Down Expand Up @@ -79,7 +79,7 @@ export async function collectBuildTraces({
staticPages: string[]
hasSsrAmpPages: boolean
outputFileTracingRoot: string
pageInfos: [string, PageInfo][]
pageInfos: Map<string, PageInfo> | undefined
nextBuildSpan?: Span
config: NextConfigComplete
buildTraceContext?: BuildTraceContext
Expand Down Expand Up @@ -638,10 +638,8 @@ export async function collectBuildTraces({
}

// edge routes have no trace files
const [, pageInfo] = pageInfos.find((item) => item[0] === route) || []
if (pageInfo?.runtime === 'edge') {
return
}
const pageInfo = pageInfos?.get(route)
if (pageInfo?.runtime === 'edge') return

const combinedIncludes = new Set<string>()
const combinedExcludes = new Set<string>()
Expand Down
147 changes: 84 additions & 63 deletions packages/next/src/build/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ import {
isReservedPage,
isAppBuiltinNotFoundPage,
} from './utils'
import type { PageInfo, AppConfig } from './utils'
import type { AppConfig } from './utils'
import { patchPageInfos, type PageInfo } from './page-info'
import { writeBuildId } from './write-build-id'
import { normalizeLocalePath } from '../shared/lib/i18n/normalize-locale-path'
import isError from '../lib/is-error'
Expand Down Expand Up @@ -349,6 +350,34 @@ function pageToRoute(page: string) {
}
}

function createAppDataRouteInfo(
page: string,
{
experimentalPPR,
isRouteHandler,
}: {
experimentalPPR: boolean | undefined
isRouteHandler: boolean
}
): DataRouteRouteInfo {
const normalizedRoute = normalizePagePath(page)

// If the page is not a route handler we need to generate a data route.
let dataRoute: string | null = null
if (!isRouteHandler) {
dataRoute = path.posix.join(`${normalizedRoute}${RSC_SUFFIX}`)
}

let prefetchDataRoute: string | undefined
if (experimentalPPR) {
prefetchDataRoute = path.posix.join(
`${normalizedRoute}${RSC_PREFETCH_SUFFIX}`
)
}

return { dataRoute, prefetchDataRoute }
}

export default async function build(
dir: string,
reactProductionProfiling = false,
Expand Down Expand Up @@ -1109,7 +1138,7 @@ export default async function build(
dir,
config,
distDir,
pageInfos: [],
pageInfos: undefined,
staticPages: [],
hasSsrAmpPages: false,
buildTraceContext,
Expand Down Expand Up @@ -1923,7 +1952,7 @@ export default async function build(
dir,
config,
distDir,
pageInfos: Object.entries(pageInfos),
pageInfos,
staticPages: [...staticPages],
nextBuildSpan,
hasSsrAmpPages,
Expand Down Expand Up @@ -2258,11 +2287,17 @@ export default async function build(
appConfig.revalidate === 0 ||
exportResult.byPath.get(page)?.revalidate === 0

if (hasDynamicData && pageInfos.get(page)?.isStatic) {
const pageInfo = pageInfos.get(page)
if (!pageInfo) {
throw new Error(
`Invariant: page info for ${page} is missing from registry`
)
}

if (hasDynamicData && pageInfo.isStatic) {
// if the page was marked as being static, but it contains dynamic data
// (ie, in the case of a static generation bailout), then it should be marked dynamic
pageInfos.set(page, {
...(pageInfos.get(page) as PageInfo),
patchPageInfos(pageInfos, page, {
isStatic: false,
isSSG: false,
})
Expand Down Expand Up @@ -2299,35 +2334,28 @@ export default async function build(
hasPostponed,
} = exportResult.byPath.get(route) ?? {}

pageInfos.set(route, {
...(pageInfos.get(route) as PageInfo),
hasPostponed,
hasEmptyPrelude,
})
// Update the page (eg /blog/[slug]) to also have the postpone
// metadata if it's changed.
if (
pageInfo.hasPostponed !== hasPostponed ||
pageInfo.hasEmptyPrelude !== hasEmptyPrelude
) {
pageInfo.hasPostponed = hasPostponed
pageInfo.hasEmptyPrelude = hasEmptyPrelude

// update the page (eg /blog/[slug]) to also have the postpone metadata
pageInfos.set(page, {
...(pageInfos.get(page) as PageInfo),
hasPostponed,
hasEmptyPrelude,
})

if (revalidate !== 0) {
const normalizedRoute = normalizePagePath(route)
pageInfos.set(page, pageInfo)
}

let dataRoute: string | null
if (isRouteHandler) {
dataRoute = null
} else {
dataRoute = path.posix.join(`${normalizedRoute}${RSC_SUFFIX}`)
}
pageInfos.set(route, pageInfo)

let prefetchDataRoute: string | null | undefined
if (experimentalPPR) {
prefetchDataRoute = path.posix.join(
`${normalizedRoute}${RSC_PREFETCH_SUFFIX}`
)
}
if (revalidate !== 0) {
const { dataRoute, prefetchDataRoute } = createAppDataRouteInfo(
route,
{
experimentalPPR,
isRouteHandler,
}
)

const routeMeta: Partial<SsgRoute> = {}

Expand Down Expand Up @@ -2373,29 +2401,23 @@ export default async function build(
hasDynamicData = true
// we might have determined during prerendering that this page
// used dynamic data
pageInfos.set(route, {
...(pageInfos.get(route) as PageInfo),
patchPageInfos(pageInfos, route, {
isSSG: false,
isStatic: false,
})
}
})

if (!hasDynamicData && isDynamicRoute(originalAppPath)) {
const normalizedRoute = normalizePagePath(page)
const dataRoute = path.posix.join(
`${normalizedRoute}${RSC_SUFFIX}`
const { dataRoute, prefetchDataRoute } = createAppDataRouteInfo(
page,
{
experimentalPPR,
isRouteHandler,
}
)

let prefetchDataRoute: string | null | undefined
if (experimentalPPR) {
prefetchDataRoute = path.posix.join(
`${normalizedRoute}${RSC_PREFETCH_SUFFIX}`
)
}

pageInfos.set(page, {
...(pageInfos.get(page) as PageInfo),
patchPageInfos(pageInfos, page, {
isDynamicAppRoute: true,
// if PPR is turned on and the route contains a dynamic segment,
// we assume it'll be partially prerendered
Expand All @@ -2410,33 +2432,32 @@ export default async function build(
routeRegex: normalizeRouteRegex(
getNamedRouteRegex(page, false).re.source
),
dataRoute,
// if dynamicParams are enabled treat as fallback:
// 'blocking' if not it's fallback: false
fallback: appDynamicParamPaths.has(originalAppPath)
? null
: false,
dataRouteRegex: isRouteHandler
? null
: normalizeRouteRegex(
dataRoute,
dataRouteRegex: dataRoute
? normalizeRouteRegex(
getNamedRouteRegex(
dataRoute.replace(/\.rsc$/, ''),
false
).re.source.replace(/\(\?:\\\/\)\?\$$/, '\\.rsc$')
),
)
: null,
prefetchDataRoute,
prefetchDataRouteRegex:
isRouteHandler || !prefetchDataRoute
? undefined
: normalizeRouteRegex(
getNamedRouteRegex(
prefetchDataRoute.replace(/\.prefetch\.rsc$/, ''),
false
).re.source.replace(
/\(\?:\\\/\)\?\$$/,
'\\.prefetch\\.rsc$'
)
),
prefetchDataRouteRegex: prefetchDataRoute
? normalizeRouteRegex(
getNamedRouteRegex(
prefetchDataRoute.replace(/\.prefetch\.rsc$/, ''),
false
).re.source.replace(
/\(\?:\\\/\)\?\$$/,
'\\.prefetch\\.rsc$'
)
)
: undefined,
}
}
}
Expand Down
43 changes: 43 additions & 0 deletions packages/next/src/build/page-info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import type { ServerRuntime } from '../../types'

export interface PageInfo {
isHybridAmp?: boolean
size: number
totalSize: number
isStatic: boolean
isSSG: boolean
isPPR: boolean
ssgPageRoutes: string[] | null
initialRevalidateSeconds: number | false
pageDuration: number | undefined
ssgPageDurations: number[] | undefined
runtime: ServerRuntime
hasEmptyPrelude?: boolean
hasPostponed?: boolean
isDynamicAppRoute?: boolean
}

/**
* Updates the page info for a given page. If the page info doesn't exist, it
* will throw an error.
*
* @param pageInfos the page infos map
* @param page the page to update
* @param update the update to apply
* @returns the updated page info
*/
export function patchPageInfos(
pageInfos: Map<string, PageInfo>,
page: string,
update: Partial<PageInfo>
): PageInfo {
const pageInfo = pageInfos.get(page)
if (!pageInfo) {
throw new Error(`Invariant: Expected page "${page}" to exist`)
}

// Patch the page info with the update.
Object.assign(pageInfo, update)

return pageInfo
}
31 changes: 10 additions & 21 deletions packages/next/src/build/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import type {
import type { WebpackLayerName } from '../lib/constants'
import type { AppPageModule } from '../server/future/route-modules/app-page/module'
import type { RouteModule } from '../server/future/route-modules/route-module'
import type { PageInfo } from './page-info'

import '../server/require-hook'
import '../server/node-polyfill-crypto'
Expand Down Expand Up @@ -324,23 +325,6 @@ const filterAndSortList = (
return pages.sort((a, b) => a.localeCompare(b))
}

export interface PageInfo {
isHybridAmp?: boolean
size: number
totalSize: number
isStatic: boolean
isSSG: boolean
isPPR: boolean
ssgPageRoutes: string[] | null
initialRevalidateSeconds: number | false
pageDuration: number | undefined
ssgPageDurations: number[] | undefined
runtime: ServerRuntime
hasEmptyPrelude?: boolean
hasPostponed?: boolean
isDynamicAppRoute?: boolean
}

export async function printTreeView(
lists: {
pages: ReadonlyArray<string>
Expand Down Expand Up @@ -645,10 +629,15 @@ export async function printTreeView(
messages.push(['', '', ''])
}

pageInfos.set('/404', {
...(pageInfos.get('/404') || pageInfos.get('/_error'))!,
isStatic: useStaticPages404,
})
// We should update the `isStatic` part of the pageInfo for the /404 page.
// When we're using experimental compile, this won't be available.
const pageInfo = pageInfos.get('/404') || pageInfos.get('/_error')
if (pageInfo) {
pageInfos.set('/404', {
...pageInfo,
isStatic: useStaticPages404,
})
}

// If there's no app /_notFound page present, then the 404 is still using the pages/404
if (!lists.pages.includes('/404') && !lists.app?.includes('/_not-found')) {
Expand Down

0 comments on commit 7b5a465

Please sign in to comment.