Skip to content

Commit c721f69

Browse files
committed
refactor: replace match with definition for ensure, added dev handler interface + typings
1 parent 7aec7fa commit c721f69

File tree

7 files changed

+107
-76
lines changed

7 files changed

+107
-76
lines changed

packages/next/src/server/dev/hot-reloader-types.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { UrlObject } from 'url'
33
import type { Duplex } from 'stream'
44
import type { webpack } from 'next/dist/compiled/webpack/webpack'
55
import type getBaseWebpackConfig from '../../build/webpack-config'
6-
import type { RouteMatch } from '../future/route-matches/route-match'
6+
import type { RouteDefinition } from '../future/route-definitions/route-definition'
77
import type { Project, Update as TurbopackUpdate } from '../../build/swc'
88
import type { VersionInfo } from './parse-version-info'
99

@@ -134,13 +134,13 @@ export interface NextJsHotReloaderInterface {
134134
page,
135135
clientOnly,
136136
appPaths,
137-
match,
137+
definition,
138138
isApp,
139139
}: {
140140
page: string
141141
clientOnly: boolean
142142
appPaths?: ReadonlyArray<string> | null
143143
isApp?: boolean
144-
match?: RouteMatch
144+
definition: RouteDefinition | undefined
145145
}): Promise<void>
146146
}

packages/next/src/server/dev/hot-reloader-webpack.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { Duplex } from 'stream'
44
import type { Telemetry } from '../../telemetry/storage'
55
import type { IncomingMessage, ServerResponse } from 'http'
66
import type { UrlObject } from 'url'
7+
import type { RouteDefinition } from '../future/route-definitions/route-definition'
78

89
import { webpack, StringXor } from 'next/dist/compiled/webpack/webpack'
910
import { getOverlayMiddleware } from 'next/dist/compiled/@next/react-dev-overlay/dist/middleware'
@@ -60,7 +61,6 @@ import ws from 'next/dist/compiled/ws'
6061
import { existsSync, promises as fs } from 'fs'
6162
import { UnwrapPromise } from '../../lib/coalesced-function'
6263
import { getRegistry } from '../../lib/helpers/get-registry'
63-
import { RouteMatch } from '../future/route-matches/route-match'
6464
import { parseVersionInfo, VersionInfo } from './parse-version-info'
6565
import { isAPIRoute } from '../../lib/is-api-route'
6666
import { getRouteLoaderEntry } from '../../build/webpack/loaders/next-route-loader'
@@ -1466,14 +1466,14 @@ export default class HotReloader implements NextJsHotReloaderInterface {
14661466
page,
14671467
clientOnly,
14681468
appPaths,
1469-
match,
1469+
definition,
14701470
isApp,
14711471
}: {
14721472
page: string
14731473
clientOnly: boolean
14741474
appPaths?: ReadonlyArray<string> | null
14751475
isApp?: boolean
1476-
match?: RouteMatch
1476+
definition?: RouteDefinition
14771477
}): Promise<void> {
14781478
// Make sure we don't re-build or dispose prebuilt pages
14791479
if (page !== '/_error' && BLOCKED_PAGES.indexOf(page) !== -1) {
@@ -1490,7 +1490,7 @@ export default class HotReloader implements NextJsHotReloaderInterface {
14901490
page,
14911491
clientOnly,
14921492
appPaths,
1493-
match,
1493+
definition,
14941494
isApp,
14951495
})
14961496
}

packages/next/src/server/dev/next-dev-server.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ import type { UrlWithParsedQuery } from 'url'
88
import type { BaseNextRequest, BaseNextResponse } from '../base-http'
99
import type { FallbackMode, MiddlewareRoutingItem } from '../base-server'
1010
import type { FunctionComponent } from 'react'
11-
import type { RouteMatch } from '../future/route-matches/route-match'
11+
import type { RouteDefinition } from '../future/route-definitions/route-definition'
1212
import type { RouteMatcherManager } from '../future/route-matcher-managers/route-matcher-manager'
1313
import type {
1414
NextParsedUrlQuery,
1515
NextUrlWithParsedQuery,
1616
} from '../request-meta'
17+
import type { DevHandlers } from '../lib/dev-handlers'
1718

1819
import fs from 'fs'
1920
import { Worker } from 'next/dist/compiled/jest-worker'
@@ -97,7 +98,17 @@ export default class DevServer extends Server {
9798
UnwrapPromise<ReturnType<DevServer['getStaticPaths']>>
9899
>
99100

100-
private invokeDevMethod({ method, args }: { method: string; args: any[] }) {
101+
private invokeDevMethod<M extends keyof DevHandlers>({
102+
method,
103+
args,
104+
}: {
105+
method: M
106+
/**
107+
* This filters out the first `dir` argument from the method signature, as
108+
* it's added by this method when invoking.
109+
*/
110+
args: DevHandlers[M] extends (_: any, ...rest: infer P) => any ? P : never
111+
}) {
101112
return (global as any)._nextDevHandlers[method](this.dir, ...args)
102113
}
103114

@@ -190,7 +201,7 @@ export default class DevServer extends Server {
190201
const ensurer: RouteEnsurer = {
191202
ensure: async (match) => {
192203
await this.ensurePage({
193-
match,
204+
definition: match.definition,
194205
page: match.definition.page,
195206
clientOnly: false,
196207
})
@@ -534,6 +545,7 @@ export default class DevServer extends Server {
534545
return this.ensurePage({
535546
page: this.actualMiddlewareFile!,
536547
clientOnly: false,
548+
definition: undefined,
537549
})
538550
}
539551

@@ -543,6 +555,7 @@ export default class DevServer extends Server {
543555
(await this.ensurePage({
544556
page: this.actualInstrumentationHookFile!,
545557
clientOnly: false,
558+
definition: undefined,
546559
})
547560
.then(() => true)
548561
.catch(() => false))
@@ -570,7 +583,12 @@ export default class DevServer extends Server {
570583
page: string
571584
appPaths: string[] | null
572585
}) {
573-
return this.ensurePage({ page, appPaths, clientOnly: false })
586+
return this.ensurePage({
587+
page,
588+
appPaths,
589+
clientOnly: false,
590+
definition: undefined,
591+
})
574592
}
575593

576594
generateRoutes(_dev?: boolean) {
@@ -723,7 +741,7 @@ export default class DevServer extends Server {
723741
page: string
724742
clientOnly: boolean
725743
appPaths?: ReadonlyArray<string> | null
726-
match?: RouteMatch
744+
definition: RouteDefinition | undefined
727745
}): Promise<void> {
728746
await this.invokeDevMethod({
729747
method: 'ensurePage',
@@ -759,6 +777,7 @@ export default class DevServer extends Server {
759777
page,
760778
appPaths,
761779
clientOnly: false,
780+
definition: undefined,
762781
})
763782
}
764783

packages/next/src/server/dev/on-demand-entry-handler.ts

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ import {
3333
COMPILER_NAMES,
3434
RSC_MODULE_TYPES,
3535
} from '../../shared/lib/constants'
36-
import { RouteMatch } from '../future/route-matches/route-match'
3736
import { HMR_ACTIONS_SENT_TO_BROWSER } from './hot-reloader-types'
3837
import HotReloader from './hot-reloader-webpack'
3938
import { isAppPageRouteDefinition } from '../future/route-definitions/app-page-route-definition'
@@ -677,13 +676,13 @@ export function onDemandEntryHandler({
677676
page,
678677
clientOnly,
679678
appPaths,
680-
match,
679+
definition,
681680
isApp,
682681
}: {
683682
page: string
684683
clientOnly: boolean
685684
appPaths: ReadonlyArray<string> | null
686-
match: Pick<RouteMatch, 'definition'> | undefined
685+
definition: RouteDefinition | undefined
687686
isApp: boolean | undefined
688687
}): Promise<void> {
689688
const stalledTime = 60
@@ -694,11 +693,11 @@ export function onDemandEntryHandler({
694693
}, stalledTime * 1000)
695694

696695
try {
697-
let definition: Pick<RouteDefinition, 'filename' | 'bundlePath' | 'page'>
698-
if (match?.definition) {
699-
definition = match.definition
696+
let route: Pick<RouteDefinition, 'filename' | 'bundlePath' | 'page'>
697+
if (definition) {
698+
route = definition
700699
} else {
701-
definition = await findPagePathData(
700+
route = await findPagePathData(
702701
rootDir,
703702
page,
704703
nextConfig.pageExtensions,
@@ -707,30 +706,26 @@ export function onDemandEntryHandler({
707706
)
708707
}
709708

710-
const isInsideAppDir = !!appDir && definition.filename.startsWith(appDir)
709+
const isInsideAppDir = !!appDir && route.filename.startsWith(appDir)
711710

712711
if (typeof isApp === 'boolean' && isApp !== isInsideAppDir) {
713712
Error.stackTraceLimit = 15
714713
throw new Error(
715714
`Ensure bailed, found path "${
716-
definition.page
715+
route.page
717716
}" does not match ensure type (${isApp ? 'app' : 'pages'})`
718717
)
719718
}
720719

721-
const pageBundleType = getPageBundleType(definition.bundlePath)
720+
const pageBundleType = getPageBundleType(route.bundlePath)
722721
const addEntry = (
723722
compilerType: CompilerNameValues
724723
): {
725724
entryKey: string
726725
newEntry: boolean
727726
shouldInvalidate: boolean
728727
} => {
729-
const entryKey = getEntryKey(
730-
compilerType,
731-
pageBundleType,
732-
definition.page
733-
)
728+
const entryKey = getEntryKey(compilerType, pageBundleType, route.page)
734729
if (
735730
curEntries[entryKey] &&
736731
// there can be an overlap in the entryKey for the instrumentation hook file and a page named the same
@@ -758,9 +753,9 @@ export function onDemandEntryHandler({
758753
curEntries[entryKey] = {
759754
type: EntryTypes.ENTRY,
760755
appPaths,
761-
absolutePagePath: definition.filename,
762-
request: definition.filename,
763-
bundlePath: definition.bundlePath,
756+
absolutePagePath: route.filename,
757+
request: route.filename,
758+
bundlePath: route.bundlePath,
764759
dispose: false,
765760
lastActiveTime: Date.now(),
766761
status: ADDED,
@@ -774,7 +769,7 @@ export function onDemandEntryHandler({
774769

775770
const staticInfo = await getStaticInfoIncludingLayouts({
776771
page,
777-
pageFilePath: definition.filename,
772+
pageFilePath: route.filename,
778773
isInsideAppDir,
779774
pageExtensions: nextConfig.pageExtensions,
780775
isDev: true,
@@ -787,7 +782,7 @@ export function onDemandEntryHandler({
787782
isInsideAppDir && staticInfo.rsc !== RSC_MODULE_TYPES.client
788783

789784
runDependingOnPageType({
790-
page: definition.page,
785+
page: route.page,
791786
pageRuntime: staticInfo.runtime,
792787
pageType: pageBundleType,
793788
onClient: () => {
@@ -802,11 +797,11 @@ export function onDemandEntryHandler({
802797
const edgeServerEntry = getEntryKey(
803798
COMPILER_NAMES.edgeServer,
804799
pageBundleType,
805-
definition.page
800+
route.page
806801
)
807802
if (
808803
curEntries[edgeServerEntry] &&
809-
!isInstrumentationHookFile(definition.page)
804+
!isInstrumentationHookFile(route.page)
810805
) {
811806
// Runtime switched from edge to server
812807
delete curEntries[edgeServerEntry]
@@ -820,11 +815,11 @@ export function onDemandEntryHandler({
820815
const serverEntry = getEntryKey(
821816
COMPILER_NAMES.server,
822817
pageBundleType,
823-
definition.page
818+
route.page
824819
)
825820
if (
826821
curEntries[serverEntry] &&
827-
!isInstrumentationHookFile(definition.page)
822+
!isInstrumentationHookFile(route.page)
828823
) {
829824
// Runtime switched from server to edge
830825
delete curEntries[serverEntry]
@@ -839,9 +834,7 @@ export function onDemandEntryHandler({
839834
const hasNewEntry = addedValues.some((entry) => entry.newEntry)
840835

841836
if (hasNewEntry) {
842-
reportTrigger(
843-
!clientOnly && hasNewEntry ? `${definition.page}` : definition.page
844-
)
837+
reportTrigger(!clientOnly && hasNewEntry ? `${route.page}` : route.page)
845838
}
846839

847840
if (entriesThatShouldBeInvalidated.length > 0) {
@@ -883,7 +876,7 @@ export function onDemandEntryHandler({
883876
page: string
884877
clientOnly: boolean
885878
appPaths?: ReadonlyArray<string> | null
886-
match?: RouteMatch
879+
definition?: RouteDefinition
887880
isApp?: boolean
888881
}
889882

@@ -907,26 +900,28 @@ export function onDemandEntryHandler({
907900
page,
908901
clientOnly,
909902
appPaths = null,
910-
match,
903+
definition,
911904
isApp,
912905
}: EnsurePageOptions) {
913906
// If the route is actually an app page route, then we should have access
914-
// to the app route match, and therefore, the appPaths from it.
915-
if (
916-
!appPaths &&
917-
match?.definition &&
918-
isAppPageRouteDefinition(match.definition)
919-
) {
920-
appPaths = match.definition.appPaths
907+
// to the app route definition, and therefore, the appPaths from it.
908+
if (!appPaths && definition && isAppPageRouteDefinition(definition)) {
909+
appPaths = definition.appPaths
921910
}
922911

923912
// Wrap the invocation of the ensurePageImpl function in the pending
924913
// wrapper, which will ensure that we don't have multiple compilations
925914
// for the same page happening concurrently.
926915
return batcher.batch(
927-
{ page, clientOnly, appPaths, match, isApp },
916+
{ page, clientOnly, appPaths, definition, isApp },
928917
async () => {
929-
await ensurePageImpl({ page, clientOnly, appPaths, match, isApp })
918+
await ensurePageImpl({
919+
page,
920+
clientOnly,
921+
appPaths,
922+
definition,
923+
isApp,
924+
})
930925
}
931926
)
932927
},
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import type { IncomingMessage } from 'http'
2+
import type { NextJsHotReloaderInterface } from '../dev/hot-reloader-types'
3+
4+
/**
5+
* The interface for the dev handlers global.
6+
*/
7+
export interface DevHandlers {
8+
ensurePage(
9+
dir: string,
10+
...args: Parameters<NextJsHotReloaderInterface['ensurePage']>
11+
): Promise<void>
12+
logErrorWithOriginalStack(
13+
dir: string,
14+
err: unknown,
15+
type?: 'unhandledRejection' | 'uncaughtException' | 'warning' | 'app-dir'
16+
): Promise<void>
17+
getFallbackErrorComponents(dir: string): Promise<void>
18+
getCompilationError(dir: string, page: string): Promise<any>
19+
revalidate(
20+
dir: string,
21+
opts: {
22+
urlPath: string
23+
revalidateHeaders: IncomingMessage['headers']
24+
opts: any
25+
}
26+
): Promise<{}>
27+
}

0 commit comments

Comments
 (0)