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

Only resolve page runtime for react 18 and error on read failure #35705

Merged
merged 6 commits into from Mar 30, 2022
Merged
Show file tree
Hide file tree
Changes from 5 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
30 changes: 19 additions & 11 deletions packages/next/build/entries.ts
@@ -1,4 +1,8 @@
import type { PageRuntime, NextConfigComplete } from '../server/config-shared'
import type {
PageRuntime,
NextConfigComplete,
NextConfig,
} from '../server/config-shared'
import type { webpack5 } from 'next/dist/compiled/webpack/webpack'
import fs from 'fs'
import chalk from 'next/dist/compiled/chalk'
Expand Down Expand Up @@ -105,8 +109,11 @@ const cachedPageRuntimeConfig = new Map<string, [number, PageRuntime]>()
// could be thousands of pages existing.
export async function getPageRuntime(
pageFilePath: string,
globalRuntimeFallback?: 'nodejs' | 'edge'
nextConfig: Partial<NextConfig>
): Promise<PageRuntime> {
if (!nextConfig.experimental?.reactRoot) return undefined

const globalRuntime = nextConfig.experimental?.runtime
const cached = cachedPageRuntimeConfig.get(pageFilePath)
if (cached) {
return cached[1]
Expand All @@ -118,6 +125,7 @@ export async function getPageRuntime(
encoding: 'utf8',
})
} catch (err) {
if (process.env.NODE_ENV === 'production') throw err
return undefined
}

Expand Down Expand Up @@ -183,7 +191,7 @@ export async function getPageRuntime(

if (!pageRuntime) {
if (isRuntimeRequired) {
pageRuntime = globalRuntimeFallback
pageRuntime = globalRuntime
}
}

Expand Down Expand Up @@ -217,6 +225,7 @@ export async function createEntrypoints(
const hasRuntimeConfig =
Object.keys(config.publicRuntimeConfig).length > 0 ||
Object.keys(config.serverRuntimeConfig).length > 0
const hasReactRoot = !!config.experimental.reactRoot

const defaultServerlessOptions = {
absoluteAppPath: pages['/_app'],
Expand All @@ -242,11 +251,9 @@ export async function createEntrypoints(
'base64'
),
i18n: config.i18n ? JSON.stringify(config.i18n) : '',
reactRoot: config.experimental.reactRoot ? 'true' : '',
reactRoot: hasReactRoot ? 'true' : '',
}

const globalRuntime = config.experimental.runtime

await Promise.all(
Object.keys(pages).map(async (page) => {
const absolutePagePath = pages[page]
Expand All @@ -260,11 +267,12 @@ export async function createEntrypoints(
const isReserved = isReservedPage(page)
const isCustomError = isCustomErrorPage(page)
const isFlight = isFlightPage(config, absolutePagePath)
const isEdgeRuntime =
(await getPageRuntime(
join(pagesDir, absolutePagePath.slice(PAGES_DIR_ALIAS.length + 1)),
globalRuntime
)) === 'edge'
const isInternalPages = !absolutePagePath.startsWith(PAGES_DIR_ALIAS)
const pageFilePath = isInternalPages
? require.resolve(absolutePagePath)
: join(pagesDir, absolutePagePath.replace(PAGES_DIR_ALIAS, ''))
const pageRuntime = await getPageRuntime(pageFilePath, config)
const isEdgeRuntime = pageRuntime === 'edge'

if (page.match(MIDDLEWARE_ROUTE)) {
const loaderOpts: MiddlewareLoaderOptions = {
Expand Down
10 changes: 3 additions & 7 deletions packages/next/build/index.ts
Expand Up @@ -971,13 +971,9 @@ export default async function build(
p.startsWith(actualPage + '.') ||
p.startsWith(actualPage + '/index.')
)
const pageRuntime =
hasConcurrentFeatures && pagePath
? await getPageRuntime(
join(pagesDir, pagePath),
config.experimental.runtime
)
: undefined
const pageRuntime = pagePath
? await getPageRuntime(join(pagesDir, pagePath), config)
: undefined

if (
!isMiddlewareRoute &&
Expand Down
2 changes: 1 addition & 1 deletion packages/next/server/dev/hot-reloader.ts
Expand Up @@ -509,7 +509,7 @@ export default class HotReloader {

const pageRuntimeConfig = await getPageRuntime(
absolutePagePath,
this.runtime
this.config
)
const isEdgeSSRPage = pageRuntimeConfig === 'edge' && !isApiRoute

Expand Down
2 changes: 1 addition & 1 deletion packages/next/server/dev/next-dev-server.ts
Expand Up @@ -285,7 +285,7 @@ export default class DevServer extends Server {
invalidatePageRuntimeCache(fileName, safeTime)
const pageRuntimeConfig = await getPageRuntime(
fileName,
this.nextConfig.experimental.runtime
this.nextConfig
)
const isEdgeRuntime = pageRuntimeConfig === 'edge'

Expand Down
2 changes: 1 addition & 1 deletion packages/next/server/dev/on-demand-entry-handler.ts
Expand Up @@ -207,7 +207,7 @@ export default function onDemandEntryHandler(
const isApiRoute = normalizedPage.match(API_ROUTE) && !isMiddleware
const pageRuntimeConfig = await getPageRuntime(
absolutePagePath,
nextConfig.experimental.runtime
nextConfig
)
const isEdgeServer = pageRuntimeConfig === 'edge'

Expand Down
20 changes: 15 additions & 5 deletions test/unit/parse-page-runtime.test.ts
@@ -1,26 +1,36 @@
import { getPageRuntime } from 'next/dist/build/entries'
import type { PageRuntime } from 'next/dist/server/config-shared'
import { join } from 'path'

const fixtureDir = join(__dirname, 'fixtures')

function createNextConfig(runtime?: PageRuntime) {
return {
experimental: { reactRoot: true, runtime },
}
}

describe('parse page runtime config', () => {
it('should parse nodejs runtime correctly', async () => {
const runtime = await getPageRuntime(
join(fixtureDir, 'page-runtime/nodejs.js')
join(fixtureDir, 'page-runtime/nodejs.js'),
createNextConfig()
)
expect(runtime).toBe('nodejs')
})

it('should parse edge runtime correctly', async () => {
const runtime = await getPageRuntime(
join(fixtureDir, 'page-runtime/edge.js')
join(fixtureDir, 'page-runtime/edge.js'),
createNextConfig()
)
expect(runtime).toBe('edge')
})

it('should return undefined if no runtime is specified', async () => {
const runtime = await getPageRuntime(
join(fixtureDir, 'page-runtime/static.js')
join(fixtureDir, 'page-runtime/static.js'),
createNextConfig()
)
expect(runtime).toBe(undefined)
})
Expand All @@ -30,15 +40,15 @@ describe('fallback to the global runtime configuration', () => {
it('should fallback when gSP is defined and exported', async () => {
const runtime = await getPageRuntime(
join(fixtureDir, 'page-runtime/fallback-with-gsp.js'),
'edge'
createNextConfig('edge')
)
expect(runtime).toBe('edge')
})

it('should fallback when gSP is re-exported from other module', async () => {
const runtime = await getPageRuntime(
join(fixtureDir, 'page-runtime/fallback-re-export-gsp.js'),
'edge'
createNextConfig('edge')
)
expect(runtime).toBe('edge')
})
Expand Down