Skip to content

Commit a027e96

Browse files
committed
refactor: add more typings and clean up export/build flows
1 parent ce42a99 commit a027e96

File tree

17 files changed

+1098
-891
lines changed

17 files changed

+1098
-891
lines changed

packages/next-swc/crates/next-core/js/src/internal/nodejs-proxy-handler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export default (routeModule: AppRouteRouteModule) => {
4242
previewModeId: 'development-id',
4343
} as any,
4444
},
45-
staticGenerationContext: {
45+
renderOpts: {
4646
supportsDynamicHTML: true,
4747
},
4848
}

packages/next/src/build/index.ts

Lines changed: 66 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ import type { PagesManifest } from './webpack/plugins/pages-manifest-plugin'
55
import type { ExportPathMap, NextConfigComplete } from '../server/config-shared'
66
import type { MiddlewareManifest } from './webpack/plugins/middleware-plugin'
77
import type { ActionManifest } from './webpack/plugins/flight-client-entry-plugin'
8-
import type { ExportOptions } from '../export'
8+
import type { ExportAppOptions, ExportAppWorker } from '../export/types'
99

1010
import '../lib/setup-exception-listeners'
11+
1112
import { loadEnvConfig } from '@next/env'
1213
import chalk from 'next/dist/compiled/chalk'
1314
import crypto from 'crypto'
1415
import { isMatch, makeRe } from 'next/dist/compiled/micromatch'
15-
import { promises as fs, existsSync as fsExistsSync } from 'fs'
16+
import fs from 'fs/promises'
1617
import os from 'os'
1718
import { Worker } from '../lib/worker'
1819
import { defaultConfig } from '../server/config-shared'
@@ -151,21 +152,29 @@ import { defaultOverrides } from '../server/require-hook'
151152
import { initialize as initializeIncrementalCache } from '../server/lib/incremental-cache-server'
152153
import { nodeFs } from '../server/lib/node-fs-methods'
153154

154-
export type SsgRoute = {
155+
interface ExperimentalBypassForInfo {
156+
experimentalBypassFor?: RouteHas[]
157+
}
158+
159+
interface DataRouteRouteInfo {
160+
dataRoute: string | null
161+
}
162+
163+
export interface SsgRoute
164+
extends ExperimentalBypassForInfo,
165+
DataRouteRouteInfo {
155166
initialRevalidateSeconds: number | false
156167
srcRoute: string | null
157-
dataRoute: string | null
158168
initialStatus?: number
159169
initialHeaders?: Record<string, string>
160-
experimentalBypassFor?: RouteHas[]
161170
}
162171

163-
export type DynamicSsgRoute = {
172+
export interface DynamicSsgRoute
173+
extends ExperimentalBypassForInfo,
174+
DataRouteRouteInfo {
164175
routeRegex: string
165176
fallback: string | null | false
166-
dataRoute: string | null
167177
dataRouteRegex: string | null
168-
experimentalBypassFor?: RouteHas[]
169178
}
170179

171180
export type PrerenderManifest = {
@@ -2489,15 +2498,10 @@ export default async function build(
24892498
ssgPages,
24902499
additionalSsgPaths
24912500
)
2492-
const exportApp: typeof import('../export').default =
2493-
require('../export').default
2501+
const exportApp: ExportAppWorker = require('../export').default
24942502

24952503
const exportConfig: NextConfigComplete = {
24962504
...config,
2497-
initialPageRevalidationMap: {},
2498-
initialPageMetaMap: {},
2499-
pageDurationMap: {},
2500-
ssgNotFoundPaths: [] as string[],
25012505
// Default map will be the collection of automatic statically exported
25022506
// pages and incremental pages.
25032507
// n.b. we cannot handle this above in combinedPages because the dynamic
@@ -2619,7 +2623,7 @@ export default async function build(
26192623
},
26202624
}
26212625

2622-
const exportOptions: ExportOptions = {
2626+
const exportOptions: ExportAppOptions = {
26232627
isInvokedFromCli: false,
26242628
nextConfig: exportConfig,
26252629
hasAppDir,
@@ -2644,10 +2648,17 @@ export default async function build(
26442648
: undefined,
26452649
}
26462650

2647-
await exportApp(dir, exportOptions, nextBuildSpan)
2651+
const exportResult = await exportApp(
2652+
dir,
2653+
exportOptions,
2654+
nextBuildSpan
2655+
)
2656+
2657+
// If there was no result, there's nothing more to do.
2658+
if (!exportResult) return
26482659

26492660
const postBuildSpinner = createSpinner('Finalizing page optimization')
2650-
ssgNotFoundPaths = exportConfig.ssgNotFoundPaths
2661+
ssgNotFoundPaths = exportResult.ssgNotFoundPaths
26512662

26522663
// remove server bundles that were exported
26532664
for (const page of staticPages) {
@@ -2659,8 +2670,7 @@ export default async function build(
26592670
const page = appNormalizedPaths.get(originalAppPath) || ''
26602671
const appConfig = appDefaultConfigs.get(originalAppPath) || {}
26612672
let hasDynamicData =
2662-
appConfig.revalidate === 0 ||
2663-
exportConfig.initialPageRevalidationMap[page] === 0
2673+
appConfig.revalidate === 0 || exportResult.revalidate[page] === 0
26642674

26652675
if (hasDynamicData && pageInfos.get(page)?.static) {
26662676
// if the page was marked as being static, but it contains dynamic data
@@ -2689,7 +2699,7 @@ export default async function build(
26892699
if (isDynamicRoute(page) && route === page) return
26902700
if (route === '/_not-found') return
26912701

2692-
let revalidate = exportConfig.initialPageRevalidationMap[route]
2702+
let revalidate = exportResult.revalidate[page]
26932703

26942704
if (typeof revalidate === 'undefined') {
26952705
revalidate =
@@ -2714,15 +2724,13 @@ export default async function build(
27142724

27152725
const routeMeta: Partial<SsgRoute> = {}
27162726

2717-
const exportRouteMeta: {
2718-
status?: number
2719-
headers?: Record<string, string>
2720-
} = exportConfig.initialPageMetaMap[route] || {}
2727+
const metadata = exportResult.metadata[route] ?? {}
27212728

2722-
if (exportRouteMeta.status !== 200) {
2723-
routeMeta.initialStatus = exportRouteMeta.status
2729+
if (metadata.status !== 200) {
2730+
routeMeta.initialStatus = metadata.status
27242731
}
2725-
const exportHeaders = exportRouteMeta.headers
2732+
2733+
const exportHeaders = metadata.headers
27262734
const headerKeys = Object.keys(exportHeaders || {})
27272735

27282736
if (exportHeaders && headerKeys.length) {
@@ -2956,7 +2964,7 @@ export default async function build(
29562964
const file = normalizePagePath(page)
29572965

29582966
const pageInfo = pageInfos.get(page)
2959-
const durationInfo = exportConfig.pageDurationMap[page]
2967+
const durationInfo = exportResult.durations[page]
29602968
if (pageInfo && durationInfo) {
29612969
// Set Build Duration
29622970
if (pageInfo.ssgPageRoutes) {
@@ -2996,9 +3004,14 @@ export default async function build(
29963004
for (const locale of i18n.locales) {
29973005
const localePage = `/${locale}${page === '/' ? '' : page}`
29983006

3007+
const initialRevalidateSeconds =
3008+
exportResult.revalidate[localePage]
3009+
if (typeof initialRevalidateSeconds === 'undefined') {
3010+
throw new Error("Invariant: locale page wasn't built")
3011+
}
3012+
29993013
finalPrerenderRoutes[localePage] = {
3000-
initialRevalidateSeconds:
3001-
exportConfig.initialPageRevalidationMap[localePage],
3014+
initialRevalidateSeconds,
30023015
srcRoute: null,
30033016
dataRoute: path.posix.join(
30043017
'/_next/data',
@@ -3008,9 +3021,13 @@ export default async function build(
30083021
}
30093022
}
30103023
} else {
3024+
const initialRevalidateSeconds = exportResult.revalidate[page]
3025+
if (typeof initialRevalidateSeconds === 'undefined') {
3026+
throw new Error("Invariant: page wasn't built")
3027+
}
3028+
30113029
finalPrerenderRoutes[page] = {
3012-
initialRevalidateSeconds:
3013-
exportConfig.initialPageRevalidationMap[page],
3030+
initialRevalidateSeconds,
30143031
srcRoute: null,
30153032
dataRoute: path.posix.join(
30163033
'/_next/data',
@@ -3021,8 +3038,12 @@ export default async function build(
30213038
}
30223039
// Set Page Revalidation Interval
30233040
if (pageInfo) {
3024-
pageInfo.initialRevalidateSeconds =
3025-
exportConfig.initialPageRevalidationMap[page]
3041+
const initialRevalidateSeconds = exportResult.revalidate[page]
3042+
if (typeof initialRevalidateSeconds === 'undefined') {
3043+
throw new Error("Invariant: page wasn't built")
3044+
}
3045+
3046+
pageInfo.initialRevalidateSeconds = initialRevalidateSeconds
30263047
}
30273048
} else {
30283049
// For a dynamic SSG page, we did not copy its data exports and only
@@ -3069,9 +3090,14 @@ export default async function build(
30693090
)
30703091
}
30713092

3093+
const initialRevalidateSeconds =
3094+
exportResult.revalidate[route]
3095+
if (typeof initialRevalidateSeconds === 'undefined') {
3096+
throw new Error("Invariant: page wasn't built")
3097+
}
3098+
30723099
finalPrerenderRoutes[route] = {
3073-
initialRevalidateSeconds:
3074-
exportConfig.initialPageRevalidationMap[route],
3100+
initialRevalidateSeconds,
30753101
srcRoute: page,
30763102
dataRoute: path.posix.join(
30773103
'/_next/data',
@@ -3082,8 +3108,7 @@ export default async function build(
30823108

30833109
// Set route Revalidation Interval
30843110
if (pageInfo) {
3085-
pageInfo.initialRevalidateSeconds =
3086-
exportConfig.initialPageRevalidationMap[route]
3111+
pageInfo.initialRevalidateSeconds = initialRevalidateSeconds
30873112
}
30883113
}
30893114
}
@@ -3296,7 +3321,7 @@ export default async function build(
32963321
)
32973322
if (appDir) {
32983323
const originalServerApp = path.join(distDir, SERVER_DIRECTORY, 'app')
3299-
if (fsExistsSync(originalServerApp)) {
3324+
if (await fileExists(originalServerApp)) {
33003325
await recursiveCopy(
33013326
originalServerApp,
33023327
path.join(
@@ -3353,8 +3378,7 @@ export default async function build(
33533378
}
33543379

33553380
if (config.output === 'export') {
3356-
const exportApp: typeof import('../export').default =
3357-
require('../export').default
3381+
const exportApp: ExportAppWorker = require('../export').default
33583382

33593383
const pagesWorker = createStaticWorker(
33603384
incrementalCacheIpcPort,
@@ -3365,7 +3389,7 @@ export default async function build(
33653389
incrementalCacheIpcValidationKey
33663390
)
33673391

3368-
const options: ExportOptions = {
3392+
const options: ExportAppOptions = {
33693393
isInvokedFromCli: false,
33703394
buildExport: false,
33713395
nextConfig: config,

packages/next/src/cli/next-export.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
#!/usr/bin/env node
2+
import type { ExportAppOptions } from '../export/types'
3+
24
import { resolve, join } from 'path'
35
import { existsSync } from 'fs'
46
import chalk from 'next/dist/compiled/chalk'
5-
import exportApp, { ExportError, ExportOptions } from '../export'
7+
import exportApp, { ExportError } from '../export'
68
import * as Log from '../build/output/log'
79
import { printAndExit } from '../server/lib/utils'
810
import { CliCommand } from '../lib/commands'
@@ -43,7 +45,7 @@ const nextExport: CliCommand = (args) => {
4345
printAndExit(`> No such directory exists as the project root: ${dir}`)
4446
}
4547

46-
const options: ExportOptions = {
48+
const options: ExportAppOptions = {
4749
silent: args['--silent'] || false,
4850
threads: args['--threads'],
4951
outdir: args['--outdir'] ? resolve(args['--outdir']) : join(dir, 'out'),

0 commit comments

Comments
 (0)