Skip to content

Commit

Permalink
refactor: cleans up the logic to de-duplicate some checks
Browse files Browse the repository at this point in the history
  • Loading branch information
wyattjoh committed Dec 8, 2023
1 parent 1f6defd commit 2da50b5
Show file tree
Hide file tree
Showing 9 changed files with 426 additions and 269 deletions.
12 changes: 5 additions & 7 deletions packages/next/src/build/collect-build-traces.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Span } from '../trace'
import type { NextConfigComplete } from '../server/config-shared'
import type { PageInfoRegistry } from './page-info'

import {
TRACE_IGNORES,
Expand All @@ -14,7 +15,6 @@ import {

import path from 'path'
import fs from 'fs/promises'
import type { PageInfo } from './utils'
import { loadBindings } from './swc'
import { nonNullable } from '../lib/non-nullable'
import * as ciEnvironment from '../telemetry/ci-info'
Expand Down Expand Up @@ -67,7 +67,7 @@ export async function collectBuildTraces({
dir,
config,
distDir,
pageInfos,
pageInfoRegistry,
staticPages,
nextBuildSpan = new Span({ name: 'build' }),
hasSsrAmpPages,
Expand All @@ -79,7 +79,7 @@ export async function collectBuildTraces({
staticPages: string[]
hasSsrAmpPages: boolean
outputFileTracingRoot: string
pageInfos: [string, PageInfo][]
pageInfoRegistry: PageInfoRegistry | 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 = pageInfoRegistry?.get(route)
if (pageInfo?.runtime === 'edge') return

const combinedIncludes = new Set<string>()
const combinedExcludes = new Set<string>()
Expand Down
168 changes: 89 additions & 79 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 { PageInfoRegistry } from './page-info'
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 @@ -349,6 +350,35 @@ function pageToRoute(page: string) {
}
}

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

// If the page is not a route handler and the page is either doesn't support
// PPR or is not PPR, 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 (supportsPPR) {
prefetchDataRoute = path.posix.join(
`${normalizedRoute}${RSC_PREFETCH_SUFFIX}`
)
}

return { dataRoute, prefetchDataRoute }
}

export default async function build(
dir: string,
reactProductionProfiling = false,
Expand Down Expand Up @@ -395,6 +425,8 @@ export default async function build(
process.env.NEXT_DEPLOYMENT_ID = config.experimental.deploymentId || ''
NextBuildContext.config = config

const nextConfigPPREnabled = config.experimental.ppr === true

let configOutDir = 'out'
if (config.output === 'export' && config.distDir !== '.next') {
// In the past, a user had to run "next build" to generate
Expand Down Expand Up @@ -1109,7 +1141,7 @@ export default async function build(
dir,
config,
distDir,
pageInfos: [],
pageInfoRegistry: undefined,
staticPages: [],
hasSsrAmpPages: false,
buildTraceContext,
Expand Down Expand Up @@ -1183,7 +1215,7 @@ export default async function build(
const appNormalizedPaths = new Map<string, string>()
const appDynamicParamPaths = new Set<string>()
const appDefaultConfigs = new Map<string, AppConfig>()
const pageInfos = new Map<string, PageInfo>()
const pageInfoRegistry = new PageInfoRegistry()
const pagesManifest = JSON.parse(
await fs.readFile(manifestPath, 'utf8')
) as PagesManifest
Expand Down Expand Up @@ -1337,7 +1369,7 @@ export default async function build(
minimalMode: ciEnvironment.hasNextSupport,
allowedRevalidateHeaderKeys:
config.experimental.allowedRevalidateHeaderKeys,
experimental: { ppr: config.experimental.ppr === true },
experimental: { ppr: nextConfigPPREnabled },
})

incrementalCacheIpcPort = cacheInitialization.ipcPort
Expand Down Expand Up @@ -1408,7 +1440,7 @@ export default async function build(
locales: config.i18n?.locales,
defaultLocale: config.i18n?.defaultLocale,
nextConfigOutput: config.output,
ppr: config.experimental.ppr === true,
nextConfigPPREnabled,
})
)

Expand Down Expand Up @@ -1620,7 +1652,7 @@ export default async function build(
maxMemoryCacheSize:
config.experimental.isrMemoryCacheSize,
nextConfigOutput: config.output,
ppr: config.experimental.ppr === true,
nextConfigPPREnabled,
})
}
)
Expand All @@ -1636,11 +1668,8 @@ export default async function build(
`Using edge runtime on a page currently disables static generation for that page`
)
} else {
// If this route can be partially pre-rendered, then
// mark it as such and mark it that it can be
// generated server-side.
if (workerResult.isPPR) {
isPPR = workerResult.isPPR
isPPR = true
isSSG = true
isStatic = true

Expand Down Expand Up @@ -1838,7 +1867,7 @@ export default async function build(
}
}

pageInfos.set(page, {
pageInfoRegistry.set(page, {
size,
totalSize,
isStatic,
Expand Down Expand Up @@ -1923,7 +1952,7 @@ export default async function build(
dir,
config,
distDir,
pageInfos: Object.entries(pageInfos),
pageInfoRegistry,
staticPages: [...staticPages],
nextBuildSpan,
hasSsrAmpPages,
Expand Down Expand Up @@ -2164,7 +2193,7 @@ export default async function build(
})

// Ensure we don't generate explicit app prefetches while in PPR.
if (config.experimental.ppr && appPrefetchPaths.size > 0) {
if (nextConfigPPREnabled && appPrefetchPaths.size > 0) {
throw new Error(
"Invariant: explicit app prefetches shouldn't generated with PPR"
)
Expand Down Expand Up @@ -2258,24 +2287,25 @@ export default async function build(
appConfig.revalidate === 0 ||
exportResult.byPath.get(page)?.revalidate === 0

if (hasDynamicData && pageInfos.get(page)?.isStatic) {
const { isStatic, isPPR } = pageInfoRegistry.get(page, true)
if (hasDynamicData && 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),
pageInfoRegistry.patch(page, {
isStatic: false,
isSSG: false,
})
}

const isRouteHandler = isAppRouteRoute(originalAppPath)

// When this is an app page and PPR is enabled, the route supports
// partial pre-rendering.
const experimentalPPR =
!isRouteHandler && config.experimental.ppr === true
? true
: undefined
/**
* If this page is not an app route and PPR is enabled, then it
* could support PPR.
*/
const supportsPPR = !isRouteHandler && nextConfigPPREnabled

const experimentalPPR = isPPR ? true : undefined

// this flag is used to selectively bypass the static cache and invoke the lambda directly
// to enable server actions on static routes
Expand All @@ -2299,35 +2329,22 @@ 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
pageInfos.set(page, {
...(pageInfos.get(page) as PageInfo),
const pageInfo = pageInfoRegistry.patch(page, {
hasPostponed,
hasEmptyPrelude,
})

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

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}`
)
}
if (revalidate !== 0) {
const { dataRoute, prefetchDataRoute } = createAppDataRouteInfo(
route,
{
supportsPPR,
isRouteHandler,
}
)

const routeMeta: Partial<SsgRoute> = {}

Expand Down Expand Up @@ -2373,33 +2390,27 @@ 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),
pageInfoRegistry.patch(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,
{
supportsPPR,
isRouteHandler,
}
)

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

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

// TODO: create a separate manifest to allow enforcing
Expand All @@ -2410,33 +2421,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 Expand Up @@ -2601,7 +2611,7 @@ export default async function build(
const hasAmp = hybridAmpPages.has(page)
const file = normalizePagePath(page)

const pageInfo = pageInfos.get(page)
const pageInfo = pageInfoRegistry.get(page)
const durationInfo = exportResult.byPage.get(page)
if (pageInfo && durationInfo) {
// Set Build Duration
Expand Down Expand Up @@ -3083,7 +3093,7 @@ export default async function build(
console.log()

await nextBuildSpan.traceChild('print-tree-view').traceAsyncFn(() =>
printTreeView(pageKeys, pageInfos, {
printTreeView(pageKeys, pageInfoRegistry, {
distPath: distDir,
buildId: buildId,
pagesDir,
Expand Down
Loading

0 comments on commit 2da50b5

Please sign in to comment.