Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update terminal tree view for switchable runtime #35394

Merged
merged 4 commits into from Mar 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 5 additions & 8 deletions packages/next/build/entries.ts
@@ -1,3 +1,5 @@
import type { PageRuntime, NextConfigComplete } from '../server/config-shared'
import type { webpack5 } from 'next/dist/compiled/webpack/webpack'
import fs from 'fs'
import chalk from 'next/dist/compiled/chalk'
import { posix, join } from 'path'
Expand All @@ -12,11 +14,9 @@ import { MiddlewareLoaderOptions } from './webpack/loaders/next-middleware-loade
import { ClientPagesLoaderOptions } from './webpack/loaders/next-client-pages-loader'
import { ServerlessLoaderQuery } from './webpack/loaders/next-serverless-loader'
import { LoadedEnvFiles } from '@next/env'
import { NextConfigComplete } from '../server/config-shared'
import { parse } from '../build/swc'
import { isCustomErrorPage, isFlightPage, isReservedPage } from './utils'
import { ssrEntries } from './webpack/plugins/middleware-plugin'
import type { webpack5 } from 'next/dist/compiled/webpack/webpack'
import {
MIDDLEWARE_RUNTIME_WEBPACK,
MIDDLEWARE_SSR_RUNTIME_WEBPACK,
Expand Down Expand Up @@ -99,17 +99,14 @@ type Entrypoints = {
edgeServer: webpack5.EntryObject
}

const cachedPageRuntimeConfig = new Map<
string,
[number, 'nodejs' | 'edge' | undefined]
>()
const cachedPageRuntimeConfig = new Map<string, [number, PageRuntime]>()

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

// Since these configurations should always be static analyzable, we can
// skip these cases that "runtime" and "gSP", "gSSP" are not included in the
Expand Down
11 changes: 5 additions & 6 deletions packages/next/build/index.ts
Expand Up @@ -969,7 +969,7 @@ export default async function build(
join(pagesDir, pagePath),
config.experimental.runtime
)
: null
: undefined

if (
!isMiddlewareRoute &&
Expand Down Expand Up @@ -1084,14 +1084,13 @@ export default async function build(
totalSize: allSize,
static: isStatic,
isSsg,
isWebSsr:
hasConcurrentFeatures &&
!isMiddlewareRoute &&
!isReservedPage(page) &&
!isCustomErrorPage(page),
isHybridAmp,
ssgPageRoutes,
initialRevalidateSeconds: false,
runtime:
!isReservedPage(page) && !isCustomErrorPage(page)
? pageRuntime
: undefined,
pageDuration: undefined,
ssgPageDurations: undefined,
})
Expand Down
9 changes: 5 additions & 4 deletions packages/next/build/utils.ts
@@ -1,3 +1,5 @@
import type { NextConfigComplete, PageRuntime } from '../server/config-shared'

import '../server/node-polyfill-fetch'
import chalk from 'next/dist/compiled/chalk'
import getGzipSize from 'next/dist/compiled/gzip-size'
Expand Down Expand Up @@ -37,7 +39,6 @@ import * as Log from './output/log'
import { loadComponents } from '../server/load-components'
import { trace } from '../trace'
import { setHttpAgentOptions } from '../server/config'
import { NextConfigComplete } from '../server/config-shared'
import isError from '../lib/is-error'
import { recursiveDelete } from '../lib/recursive-delete'
import { Sema } from 'next/dist/compiled/async-sema'
Expand Down Expand Up @@ -77,11 +78,11 @@ export interface PageInfo {
totalSize: number
static: boolean
isSsg: boolean
isWebSsr: boolean
ssgPageRoutes: string[] | null
initialRevalidateSeconds: number | false
pageDuration: number | undefined
ssgPageDurations: number[] | undefined
runtime: PageRuntime
}

export async function printTreeView(
Expand Down Expand Up @@ -195,12 +196,12 @@ export async function printTreeView(
? ' '
: item.endsWith('/_middleware')
? 'ƒ'
: pageInfo?.isWebSsr
? 'ℇ'
: pageInfo?.static
? '○'
: pageInfo?.isSsg
? '●'
: pageInfo?.runtime === 'edge'
? 'ℇ'
: 'λ'

usedSymbols.add(symbol)
Expand Down
4 changes: 3 additions & 1 deletion packages/next/server/config-shared.ts
Expand Up @@ -7,6 +7,8 @@ import {
imageConfigDefault,
} from '../shared/lib/image-config'

export type PageRuntime = 'nodejs' | 'edge' | undefined

export type NextConfigComplete = Required<NextConfig> & {
images: Required<ImageConfigComplete>
typescript: Required<TypeScriptConfig>
Expand Down Expand Up @@ -101,7 +103,7 @@ export interface ExperimentalConfig {
craCompat?: boolean
esmExternals?: boolean | 'loose'
isrMemoryCacheSize?: number
runtime?: 'nodejs' | 'edge'
runtime?: Exclude<PageRuntime, undefined>
serverComponents?: boolean
fullySpecified?: boolean
urlImports?: NonNullable<webpack5.Configuration['experiments']>['buildHttp']
Expand Down
@@ -1,34 +1,16 @@
/* eslint-env jest */

import { join } from 'path'
import {
// File,
nextBuild as _nextBuild,
nextStart as _nextStart,
} from 'next-test-utils'

import { findPort, killApp, renderViaHTTP } from 'next-test-utils'

const nodeArgs = ['-r', join(__dirname, '../../react-18/test/require-hook.js')]
import { nextBuild, nextStart } from './utils'

const appDir = join(__dirname, '../switchable-runtime')
// const nextConfig = new File(join(appDir, 'next.config.js'))

async function nextBuild(dir, options) {
return await _nextBuild(dir, [], {
...options,
stdout: true,
stderr: true,
nodeArgs,
})
}

async function nextStart(dir, port) {
return await _nextStart(dir, port, {
stdout: true,
stderr: true,
nodeArgs,
})
function splitLines(text) {
return text
.split(/\r?\n/g)
.map((str) => str.trim())
.filter(Boolean)
}

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

beforeAll(async () => {
context.appPort = await findPort()
const { stderr } = await nextBuild(context.appDir)
const { stdout, stderr } = await nextBuild(context.appDir)
context.stdout = stdout
context.stderr = stderr
context.server = await nextStart(context.appDir, context.appPort)
})
Expand Down Expand Up @@ -124,4 +107,26 @@ describe('Without global runtime configuration', () => {
isEdge: true,
})
})

it('should display correct tree view with page types in terminal', async () => {
const stdoutLines = splitLines(context.stdout).filter((line) =>
/^[┌├└/]/.test(line)
)
const expectedOutputLines = splitLines(`
┌ λ /404
├ ℇ /edge
├ ℇ /edge-rsc
├ ○ /node
├ ○ /node-rsc
├ ● /node-rsc-ssg
├ λ /node-rsc-ssr
├ ● /node-ssg
├ λ /node-ssr
└ ○ /static
`)
const isMatched = expectedOutputLines.every((line, index) =>
stdoutLines[index].startsWith(line)
)
expect(isMatched).toBe(true)
})
})