Skip to content

Commit

Permalink
Page Info Cleanup (#59430)
Browse files Browse the repository at this point in the history
This updates the some of the logic around updating `PageInfo` entries in
the `pageInfos` map. This is a followup to #59420.

Closes NEXT-1838
  • Loading branch information
wyattjoh authored Dec 12, 2023
1 parent d397b39 commit ed12b55
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 104 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 @@ -642,10 +642,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
152 changes: 75 additions & 77 deletions packages/next/src/build/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { MiddlewareManifest } from './webpack/plugins/middleware-plugin'
import type { ActionManifest } from './webpack/plugins/flight-client-entry-plugin'
import type { ExportAppOptions, ExportAppWorker } from '../export/types'
import type { Revalidate } from '../server/lib/revalidate'
import type { PageInfo } from './page-info'

import '../lib/setup-exception-listeners'

Expand Down Expand Up @@ -115,7 +116,7 @@ import {
isReservedPage,
isAppBuiltinNotFoundPage,
} from './utils'
import type { PageInfo, AppConfig } from './utils'
import type { AppConfig } from './utils'
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 @@ -160,6 +161,7 @@ import type { BuildTraceContext } from './webpack/plugins/next-trace-entrypoints
import { formatManifest } from './manifests/formatter/format-manifest'
import { getStartServerInfo, logStartInfo } from '../server/lib/app-info-log'
import type { NextEnabledDirectories } from '../server/base-server'
import { RouteKind } from '../server/future/route-kind'

interface ExperimentalBypassForInfo {
experimentalBypassFor?: RouteHas[]
Expand Down Expand Up @@ -1109,7 +1111,7 @@ export default async function build(
dir,
config,
distDir,
pageInfos: [],
pageInfos: undefined,
staticPages: [],
hasSsrAmpPages: false,
buildTraceContext,
Expand Down Expand Up @@ -1923,7 +1925,7 @@ export default async function build(
dir,
config,
distDir,
pageInfos: Object.entries(pageInfos),
pageInfos,
staticPages: [...staticPages],
nextBuildSpan,
hasSsrAmpPages,
Expand Down Expand Up @@ -2258,22 +2260,30 @@ export default async function build(
appConfig.revalidate === 0 ||
exportResult.byPath.get(page)?.revalidate === 0

if (hasDynamicData && pageInfos.get(page)?.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),
isStatic: false,
isSSG: false,
})
const pageInfo = pageInfos.get(page)
if (!pageInfo) {
throw new Error(
`Invariant: page info for ${page} is missing from registry`
)
}

const isRouteHandler = isAppRouteRoute(originalAppPath)
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.
pageInfo.isStatic = false
pageInfo.isSSG = false
}

const isDynamic = isDynamicRoute(page)
const kind = isAppRouteRoute(originalAppPath)
? RouteKind.APP_ROUTE
: RouteKind.APP_PAGE

// When this is an app page and PPR is enabled, the route supports
// partial pre-rendering.
const experimentalPPR =
!isRouteHandler && config.experimental.ppr === true
kind === RouteKind.APP_PAGE && config.experimental.ppr === true
? true
: undefined

Expand All @@ -2299,34 +2309,27 @@ export default async function build(
hasPostponed,
} = exportResult.byPath.get(route) ?? {}

pageInfos.set(route, {
...(pageInfos.get(route) as PageInfo),
hasPostponed,
hasEmptyPrelude,
})
// If this route postponed and/or had an empty prelude, then
// mark the page as having postponed and/or an empty prelude.
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,
})
// Link the same pageInfo used for the `page` to this specific
// `route` as they should all share the same characteristics.
pageInfos.set(route, pageInfo)

if (revalidate !== 0) {
const normalizedRoute = normalizePagePath(route)

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

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

// If this is for an app page, then we should associate a data
// route (and prefetch if PPR is enabled) for it.
if (kind === RouteKind.APP_PAGE) {
const normalized = normalizePagePath(route)
dataRoute = `${normalized}${RSC_SUFFIX}`
if (experimentalPPR) {
prefetchDataRoute = `${normalized}${RSC_PREFETCH_SUFFIX}`
}
}

const routeMeta: Partial<SsgRoute> = {}
Expand Down Expand Up @@ -2373,34 +2376,30 @@ 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),
isSSG: false,
isStatic: false,
})
pageInfo.isStatic = false
pageInfo.isSSG = false
}
})

if (!hasDynamicData && isDynamicRoute(originalAppPath)) {
const normalizedRoute = normalizePagePath(page)
const dataRoute = path.posix.join(
`${normalizedRoute}${RSC_SUFFIX}`
)
if (!hasDynamicData && isDynamic) {
let dataRoute: string | null = null
let prefetchDataRoute: string | undefined

let prefetchDataRoute: string | null | undefined
if (experimentalPPR) {
prefetchDataRoute = path.posix.join(
`${normalizedRoute}${RSC_PREFETCH_SUFFIX}`
)
// If this is for an app page, then we should associate a data
// route (and prefetch if PPR is enabled) for it.
if (kind === RouteKind.APP_PAGE) {
const normalized = normalizePagePath(page)
dataRoute = `${normalized}${RSC_SUFFIX}`
if (experimentalPPR) {
prefetchDataRoute = `${normalized}${RSC_PREFETCH_SUFFIX}`
}
}

pageInfos.set(page, {
...(pageInfos.get(page) as PageInfo),
isDynamicAppRoute: true,
// if PPR is turned on and the route contains a dynamic segment,
// we assume it'll be partially prerendered
hasPostponed: experimentalPPR,
})
pageInfo.isDynamicAppRoute = true

// If PPR is turned on and the route contains a dynamic segment,
// we assume it'll be partially prerendered
pageInfo.hasPostponed = experimentalPPR

// TODO: create a separate manifest to allow enforcing
// dynamicParams for non-static paths?
Expand All @@ -2410,33 +2409,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
18 changes: 18 additions & 0 deletions packages/next/src/build/page-info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
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
}
31 changes: 10 additions & 21 deletions packages/next/src/build/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import type { AppPageModule } from '../server/future/route-modules/app-page/modu
import type { RouteModule } from '../server/future/route-modules/route-module'
import type { LoaderTree } from '../server/lib/app-dir-module'
import type { NextComponentType } from '../shared/lib/utils'
import type { PageInfo } from './page-info'

import '../server/require-hook'
import '../server/node-polyfill-crypto'
Expand Down Expand Up @@ -326,23 +327,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 @@ -647,10 +631,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 ed12b55

Please sign in to comment.