Skip to content

Commit d41f8a5

Browse files
authored
Update terminal tree view for switchable runtime (#35394)
* Update terminal tree view for switchable runtime * share PageRuntime type * fix lint
1 parent 4f6bb5e commit d41f8a5

5 files changed

Lines changed: 48 additions & 44 deletions

File tree

packages/next/build/entries.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { PageRuntime, NextConfigComplete } from '../server/config-shared'
2+
import type { webpack5 } from 'next/dist/compiled/webpack/webpack'
13
import fs from 'fs'
24
import chalk from 'next/dist/compiled/chalk'
35
import { posix, join } from 'path'
@@ -12,11 +14,9 @@ import { MiddlewareLoaderOptions } from './webpack/loaders/next-middleware-loade
1214
import { ClientPagesLoaderOptions } from './webpack/loaders/next-client-pages-loader'
1315
import { ServerlessLoaderQuery } from './webpack/loaders/next-serverless-loader'
1416
import { LoadedEnvFiles } from '@next/env'
15-
import { NextConfigComplete } from '../server/config-shared'
1617
import { parse } from '../build/swc'
1718
import { isCustomErrorPage, isFlightPage, isReservedPage } from './utils'
1819
import { ssrEntries } from './webpack/plugins/middleware-plugin'
19-
import type { webpack5 } from 'next/dist/compiled/webpack/webpack'
2020
import {
2121
MIDDLEWARE_RUNTIME_WEBPACK,
2222
MIDDLEWARE_SSR_RUNTIME_WEBPACK,
@@ -99,17 +99,14 @@ type Entrypoints = {
9999
edgeServer: webpack5.EntryObject
100100
}
101101

102-
const cachedPageRuntimeConfig = new Map<
103-
string,
104-
[number, 'nodejs' | 'edge' | undefined]
105-
>()
102+
const cachedPageRuntimeConfig = new Map<string, [number, PageRuntime]>()
106103

107104
// @TODO: We should limit the maximum concurrency of this function as there
108105
// could be thousands of pages existing.
109106
export async function getPageRuntime(
110107
pageFilePath: string,
111108
globalRuntimeFallback?: 'nodejs' | 'edge'
112-
): Promise<'nodejs' | 'edge' | undefined> {
109+
): Promise<PageRuntime> {
113110
const cached = cachedPageRuntimeConfig.get(pageFilePath)
114111
if (cached) {
115112
return cached[1]
@@ -129,7 +126,7 @@ export async function getPageRuntime(
129126
// discussion:
130127
// https://github.com/vercel/next.js/discussions/34179
131128
let isRuntimeRequired: boolean = false
132-
let pageRuntime: 'nodejs' | 'edge' | undefined = undefined
129+
let pageRuntime: PageRuntime = undefined
133130

134131
// Since these configurations should always be static analyzable, we can
135132
// skip these cases that "runtime" and "gSP", "gSSP" are not included in the

packages/next/build/index.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,7 @@ export default async function build(
969969
join(pagesDir, pagePath),
970970
config.experimental.runtime
971971
)
972-
: null
972+
: undefined
973973

974974
if (
975975
!isMiddlewareRoute &&
@@ -1084,14 +1084,13 @@ export default async function build(
10841084
totalSize: allSize,
10851085
static: isStatic,
10861086
isSsg,
1087-
isWebSsr:
1088-
hasConcurrentFeatures &&
1089-
!isMiddlewareRoute &&
1090-
!isReservedPage(page) &&
1091-
!isCustomErrorPage(page),
10921087
isHybridAmp,
10931088
ssgPageRoutes,
10941089
initialRevalidateSeconds: false,
1090+
runtime:
1091+
!isReservedPage(page) && !isCustomErrorPage(page)
1092+
? pageRuntime
1093+
: undefined,
10951094
pageDuration: undefined,
10961095
ssgPageDurations: undefined,
10971096
})

packages/next/build/utils.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { NextConfigComplete, PageRuntime } from '../server/config-shared'
2+
13
import '../server/node-polyfill-fetch'
24
import chalk from 'next/dist/compiled/chalk'
35
import getGzipSize from 'next/dist/compiled/gzip-size'
@@ -37,7 +39,6 @@ import * as Log from './output/log'
3739
import { loadComponents } from '../server/load-components'
3840
import { trace } from '../trace'
3941
import { setHttpAgentOptions } from '../server/config'
40-
import { NextConfigComplete } from '../server/config-shared'
4142
import isError from '../lib/is-error'
4243
import { recursiveDelete } from '../lib/recursive-delete'
4344
import { Sema } from 'next/dist/compiled/async-sema'
@@ -77,11 +78,11 @@ export interface PageInfo {
7778
totalSize: number
7879
static: boolean
7980
isSsg: boolean
80-
isWebSsr: boolean
8181
ssgPageRoutes: string[] | null
8282
initialRevalidateSeconds: number | false
8383
pageDuration: number | undefined
8484
ssgPageDurations: number[] | undefined
85+
runtime: PageRuntime
8586
}
8687

8788
export async function printTreeView(
@@ -195,12 +196,12 @@ export async function printTreeView(
195196
? ' '
196197
: item.endsWith('/_middleware')
197198
? 'ƒ'
198-
: pageInfo?.isWebSsr
199-
? 'ℇ'
200199
: pageInfo?.static
201200
? '○'
202201
: pageInfo?.isSsg
203202
? '●'
203+
: pageInfo?.runtime === 'edge'
204+
? 'ℇ'
204205
: 'λ'
205206

206207
usedSymbols.add(symbol)

packages/next/server/config-shared.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {
77
imageConfigDefault,
88
} from '../shared/lib/image-config'
99

10+
export type PageRuntime = 'nodejs' | 'edge' | undefined
11+
1012
export type NextConfigComplete = Required<NextConfig> & {
1113
images: Required<ImageConfigComplete>
1214
typescript: Required<TypeScriptConfig>
@@ -101,7 +103,7 @@ export interface ExperimentalConfig {
101103
craCompat?: boolean
102104
esmExternals?: boolean | 'loose'
103105
isrMemoryCacheSize?: number
104-
runtime?: 'nodejs' | 'edge'
106+
runtime?: Exclude<PageRuntime, undefined>
105107
serverComponents?: boolean
106108
fullySpecified?: boolean
107109
urlImports?: NonNullable<webpack5.Configuration['experiments']>['buildHttp']

test/integration/react-streaming-and-server-components/test/switchable-runtime.test.js

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,16 @@
11
/* eslint-env jest */
22

33
import { join } from 'path'
4-
import {
5-
// File,
6-
nextBuild as _nextBuild,
7-
nextStart as _nextStart,
8-
} from 'next-test-utils'
9-
104
import { findPort, killApp, renderViaHTTP } from 'next-test-utils'
11-
12-
const nodeArgs = ['-r', join(__dirname, '../../react-18/test/require-hook.js')]
5+
import { nextBuild, nextStart } from './utils'
136

147
const appDir = join(__dirname, '../switchable-runtime')
15-
// const nextConfig = new File(join(appDir, 'next.config.js'))
16-
17-
async function nextBuild(dir, options) {
18-
return await _nextBuild(dir, [], {
19-
...options,
20-
stdout: true,
21-
stderr: true,
22-
nodeArgs,
23-
})
24-
}
258

26-
async function nextStart(dir, port) {
27-
return await _nextStart(dir, port, {
28-
stdout: true,
29-
stderr: true,
30-
nodeArgs,
31-
})
9+
function splitLines(text) {
10+
return text
11+
.split(/\r?\n/g)
12+
.map((str) => str.trim())
13+
.filter(Boolean)
3214
}
3315

3416
async function testRoute(appPort, url, { isStatic, isEdge }) {
@@ -54,7 +36,8 @@ describe('Without global runtime configuration', () => {
5436

5537
beforeAll(async () => {
5638
context.appPort = await findPort()
57-
const { stderr } = await nextBuild(context.appDir)
39+
const { stdout, stderr } = await nextBuild(context.appDir)
40+
context.stdout = stdout
5841
context.stderr = stderr
5942
context.server = await nextStart(context.appDir, context.appPort)
6043
})
@@ -124,4 +107,26 @@ describe('Without global runtime configuration', () => {
124107
isEdge: true,
125108
})
126109
})
110+
111+
it('should display correct tree view with page types in terminal', async () => {
112+
const stdoutLines = splitLines(context.stdout).filter((line) =>
113+
/^[/]/.test(line)
114+
)
115+
const expectedOutputLines = splitLines(`
116+
┌ λ /404
117+
├ ℇ /edge
118+
├ ℇ /edge-rsc
119+
├ ○ /node
120+
├ ○ /node-rsc
121+
├ ● /node-rsc-ssg
122+
├ λ /node-rsc-ssr
123+
├ ● /node-ssg
124+
├ λ /node-ssr
125+
└ ○ /static
126+
`)
127+
const isMatched = expectedOutputLines.every((line, index) =>
128+
stdoutLines[index].startsWith(line)
129+
)
130+
expect(isMatched).toBe(true)
131+
})
127132
})

0 commit comments

Comments
 (0)