Skip to content

Commit d937203

Browse files
authored
Implement initial handler interface for pages routes (#79260)
Continuation of #78166 this implements the `handler` interface for pages routes, This does not move the response handling inside of the handler yet as that will be in a follow-up PR to keep the changes isolated. This still returns the `RenderResult` for the `base-server` to continue to handle. Validated against `vercel/vercel` deploy tests here vercel/vercel#13349
1 parent 5136f8e commit d937203

File tree

36 files changed

+1016
-270
lines changed

36 files changed

+1016
-270
lines changed

packages/next/errors.json

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -678,11 +678,17 @@
678678
"677": "`trackDynamicImport` should always receive a promise. Something went wrong in the dynamic imports transform.",
679679
"678": "CacheSignal got more endRead() calls than beginRead() calls",
680680
"679": "A CacheSignal cannot subscribe to itself",
681-
"680": "CacheSignal cannot be used in the edge runtime, because `dynamicIO` does not support it.",
682-
"681": "Dynamic imports should not be instrumented in the edge runtime, because `dynamicIO` doesn't support it",
683-
"682": "\\`experimental.ppr\\` can not be \\`%s\\` when \\`experimental.dynamicIO\\` is \\`true\\`. PPR is implicitly enabled when Dynamic IO is enabled.",
684-
"683": "The \\`compiler.define\\` option is configured to replace the \\`%s\\` variable. This variable is either part of a Next.js built-in or is already configured.",
685-
"684": "The \\`compiler.defineServer\\` option is configured to replace the \\`%s\\` variable. This variable is either part of a Next.js built-in or is already configured.",
686-
"685": "Accessed fallback \\`params\\` during prerendering.",
687-
"686": "Expected clientReferenceManifest to be defined."
681+
"680": "Invariant: missing result from invoking %s",
682+
"681": "Invariant: missing result from invoking %s handler",
683+
"682": "Invariant: missing result",
684+
"683": "Invariant: missing result from ",
685+
"684": "Invariant: missing result from ino",
686+
"685": "CacheSignal cannot be used in the edge runtime, because `dynamicIO` does not support it.",
687+
"686": "\\`experimental.ppr\\` can not be \\`%s\\` when \\`experimental.dynamicIO\\` is \\`true\\`. PPR is implicitly enabled when Dynamic IO is enabled.",
688+
"687": "Dynamic imports should not be instrumented in the edge runtime, because `dynamicIO` doesn't support it",
689+
"688": "The \\`compiler.define\\` option is configured to replace the \\`%s\\` variable. This variable is either part of a Next.js built-in or is already configured.",
690+
"689": "The \\`compiler.defineServer\\` option is configured to replace the \\`%s\\` variable. This variable is either part of a Next.js built-in or is already configured.",
691+
"690": "Invariant: loadManifests called for edge runtime",
692+
"691": "Accessed fallback \\`params\\` during prerendering.",
693+
"692": "Expected clientReferenceManifest to be defined."
688694
}

packages/next/src/build/define-env.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { I18NDomains, NextConfigComplete } from '../server/config-shared'
22
import type { MiddlewareMatcher } from './analysis/get-page-static-info'
3+
import path from 'node:path'
34
import { needsExperimentalReact } from '../lib/needs-experimental-react'
45
import { checkIsAppPPREnabled } from '../server/lib/experimental/ppr'
56
import {
@@ -20,6 +21,7 @@ export interface DefineEnvOptions {
2021
config: NextConfigComplete
2122
dev: boolean
2223
distDir: string
24+
projectPath: string
2325
fetchCacheKeyPrefix: string | undefined
2426
hasRewrites: boolean
2527
isClient: boolean
@@ -89,6 +91,7 @@ export function getDefineEnv({
8991
config,
9092
dev,
9193
distDir,
94+
projectPath,
9295
fetchCacheKeyPrefix,
9396
hasRewrites,
9497
isClient,
@@ -275,6 +278,10 @@ export function getDefineEnv({
275278
...(isNodeServer
276279
? {
277280
'process.env.__NEXT_RELATIVE_DIST_DIR': config.distDir,
281+
'process.env.__NEXT_RELATIVE_PROJECT_DIR': path.relative(
282+
process.cwd(),
283+
projectPath
284+
),
278285
}
279286
: {}),
280287
'process.env.__NEXT_DEVTOOL_SEGMENT_EXPLORER':

packages/next/src/build/index.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ async function writeFunctionsConfigManifest(
551551
)
552552
}
553553

554-
interface RequiredServerFilesManifest {
554+
export interface RequiredServerFilesManifest {
555555
version: number
556556
config: NextConfigComplete
557557
appDir: string
@@ -2262,8 +2262,6 @@ export default async function build(
22622262
...config.experimental,
22632263
cacheHandlers: normalizedCacheHandlers,
22642264
trustHostHeader: ciEnvironment.hasNextSupport,
2265-
2266-
// @ts-expect-error internal field TODO: fix this, should use a separate mechanism to pass the info.
22672265
isExperimentalCompile: isCompileMode,
22682266
},
22692267
},
@@ -2322,6 +2320,7 @@ export default async function build(
23222320
BUILD_ID_FILE,
23232321
path.join(SERVER_DIRECTORY, NEXT_FONT_MANIFEST + '.js'),
23242322
path.join(SERVER_DIRECTORY, NEXT_FONT_MANIFEST + '.json'),
2323+
SERVER_FILES_MANIFEST,
23252324
...instrumentationHookEntryFiles,
23262325
]
23272326
.filter(nonNullable)

packages/next/src/build/swc/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ export function createDefineEnv({
386386
config,
387387
dev,
388388
distDir,
389+
projectPath,
389390
fetchCacheKeyPrefix,
390391
hasRewrites,
391392
middlewareMatchers,
@@ -407,6 +408,7 @@ export function createDefineEnv({
407408
config,
408409
dev,
409410
distDir,
411+
projectPath,
410412
fetchCacheKeyPrefix,
411413
hasRewrites,
412414
isClient: variant === 'client',

packages/next/src/build/templates/app-page.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,5 @@ export const routeModule = new AppPageRouteModule({
4949
loaderTree: tree,
5050
},
5151
distDir: process.env.__NEXT_RELATIVE_DIST_DIR || '',
52+
projectDir: process.env.__NEXT_RELATIVE_PROJECT_DIR || '',
5253
})

packages/next/src/build/templates/app-route.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const routeModule = new AppRouteRouteModule({
2525
bundlePath: 'VAR_DEFINITION_BUNDLE_PATH',
2626
},
2727
distDir: process.env.__NEXT_RELATIVE_DIST_DIR || '',
28+
projectDir: process.env.__NEXT_RELATIVE_PROJECT_DIR || '',
2829
resolvedPagePath: 'VAR_RESOLVED_PAGE_PATH',
2930
nextConfigOutput,
3031
userland,

packages/next/src/build/templates/pages-api.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { hoist } from './helpers'
1212
import * as userland from 'VAR_USERLAND'
1313
import { getTracer, SpanKind } from '../../server/lib/trace/tracer'
1414
import { BaseServerSpan } from '../../server/lib/trace/constants'
15+
import type { InstrumentationOnRequestError } from '../../server/instrumentation/types'
1516

1617
// Re-export the handler (should be the default export).
1718
export default hoist(userland, 'default')
@@ -31,6 +32,7 @@ const routeModule = new PagesAPIRouteModule({
3132
},
3233
userland,
3334
distDir: process.env.__NEXT_RELATIVE_DIST_DIR || '',
35+
projectDir: process.env.__NEXT_RELATIVE_PROJECT_DIR || '',
3436
})
3537

3638
export async function handler(
@@ -44,11 +46,12 @@ export async function handler(
4446

4547
// turbopack doesn't normalize `/index` in the page name
4648
// so we need to to process dynamic routes properly
49+
// TODO: fix turbopack providing differing value from webpack
4750
if (process.env.TURBOPACK) {
48-
srcPage = srcPage.replace(/\/index$/, '')
51+
srcPage = srcPage.replace(/\/index$/, '') || '/'
4952
}
5053

51-
const prepareResult = await routeModule.prepare(req, srcPage)
54+
const prepareResult = await routeModule.prepare(req, res, { srcPage })
5255

5356
if (!prepareResult) {
5457
res.statusCode = 400
@@ -64,11 +67,16 @@ export async function handler(
6467
const tracer = getTracer()
6568

6669
const activeSpan = tracer.getActiveScopeSpan()
70+
const onRequestError =
71+
routeModule.instrumentationOnRequestError.bind(routeModule)
6772

6873
const invokeRouteModule = async (span?: Span) =>
6974
routeModule
7075
.render(req, res, {
71-
query,
76+
query: {
77+
...query,
78+
...params,
79+
},
7280
params,
7381
allowedRevalidateHeaderKeys: process.env
7482
.__NEXT_ALLOWED_REVALIDATE_HEADERS as any as string[],
@@ -81,8 +89,10 @@ export async function handler(
8189
propagateError: false,
8290
dev: routeModule.isDev,
8391
page: 'VAR_DEFINITION_PAGE',
92+
projectDir: process.env.__NEXT_RELATIVE_PROJECT_DIR || '',
8493

85-
onError: routeModule.instrumentationOnRequestError.bind(routeModule),
94+
onError: (...args: Parameters<InstrumentationOnRequestError>) =>
95+
onRequestError(req, ...args),
8696
})
8797
.finally(() => {
8898
if (!span) return

0 commit comments

Comments
 (0)