From 050c99997f266a1bb33ec7db64aab07fdff30093 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 12 Feb 2024 11:31:21 +0100 Subject: [PATCH 01/12] More refactors --- .../src/server/dev/hot-reloader-turbopack.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/next/src/server/dev/hot-reloader-turbopack.ts b/packages/next/src/server/dev/hot-reloader-turbopack.ts index 2842b56a9126c..b5d781b638439 100644 --- a/packages/next/src/server/dev/hot-reloader-turbopack.ts +++ b/packages/next/src/server/dev/hot-reloader-turbopack.ts @@ -271,7 +271,7 @@ export async function createHotReloaderTurbopack( serverAddr: `127.0.0.1:${opts.port}`, }) const iter = project.entrypointsSubscribe() - const curEntries: Map = new Map() + const currentEntries: Map = new Map() const changeSubscriptions: Map< string, Promise> @@ -626,12 +626,12 @@ export async function createHotReloaderTurbopack( ? (normalizeRewritesForBuildManifest(rewrites) as any) : { afterFiles: [], beforeFiles: [], fallback: [] }, ...Object.fromEntries( - [...curEntries.keys()].map((pathname) => [ + [...currentEntries.keys()].map((pathname) => [ pathname, `static/chunks/pages${pathname === '/' ? '/index' : pathname}.js`, ]) ), - sortedPages: [...curEntries.keys()], + sortedPages: [...currentEntries.keys()], } const buildManifestJs = `self.__BUILD_MANIFEST = ${JSON.stringify( content @@ -838,7 +838,7 @@ export async function createHotReloaderTurbopack( globalEntries.document = entrypoints.pagesDocumentEndpoint globalEntries.error = entrypoints.pagesErrorEndpoint - curEntries.clear() + currentEntries.clear() for (const [pathname, route] of entrypoints.routes) { switch (route.type) { @@ -846,7 +846,7 @@ export async function createHotReloaderTurbopack( case 'page-api': case 'app-page': case 'app-route': { - curEntries.set(pathname, route) + currentEntries.set(pathname, route) break } default: @@ -861,7 +861,7 @@ export async function createHotReloaderTurbopack( continue } - if (!curEntries.has(pathname)) { + if (!currentEntries.has(pathname)) { const subscription = await subscriptionPromise subscription.return?.() changeSubscriptions.delete(pathname) @@ -1455,8 +1455,8 @@ export async function createHotReloaderTurbopack( } await currentEntriesHandling const route = - curEntries.get(page) ?? - curEntries.get( + currentEntries.get(page) ?? + currentEntries.get( normalizeAppPath( normalizeMetadataRoute(definition?.page ?? inputPage) ) From a063c72796bd1675aebcee1a4e521d1ac4a4357c Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 12 Feb 2024 11:34:26 +0100 Subject: [PATCH 02/12] Naming improvements --- .../src/server/dev/hot-reloader-turbopack.ts | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/packages/next/src/server/dev/hot-reloader-turbopack.ts b/packages/next/src/server/dev/hot-reloader-turbopack.ts index b5d781b638439..790edcbd41888 100644 --- a/packages/next/src/server/dev/hot-reloader-turbopack.ts +++ b/packages/next/src/server/dev/hot-reloader-turbopack.ts @@ -270,14 +270,14 @@ export async function createHotReloaderTurbopack( }), serverAddr: `127.0.0.1:${opts.port}`, }) - const iter = project.entrypointsSubscribe() + const entrypointsSubscription = project.entrypointsSubscribe() const currentEntries: Map = new Map() const changeSubscriptions: Map< string, Promise> > = new Map() let prevMiddleware: boolean | undefined = undefined - const globalEntries: { + const globalEntrypoints: { app: Endpoint | undefined document: Endpoint | undefined error: Endpoint | undefined @@ -827,16 +827,16 @@ export async function createHotReloaderTurbopack( try { async function handleEntries() { - for await (const entrypoints of iter) { + for await (const entrypoints of entrypointsSubscription) { if (!currentEntriesHandlingResolve) { currentEntriesHandling = new Promise( // eslint-disable-next-line no-loop-func (resolve) => (currentEntriesHandlingResolve = resolve) ) } - globalEntries.app = entrypoints.pagesAppEndpoint - globalEntries.document = entrypoints.pagesDocumentEndpoint - globalEntries.error = entrypoints.pagesErrorEndpoint + globalEntrypoints.app = entrypoints.pagesAppEndpoint + globalEntrypoints.document = entrypoints.pagesDocumentEndpoint + globalEntrypoints.error = entrypoints.pagesErrorEndpoint currentEntries.clear() @@ -1031,20 +1031,20 @@ export async function createHotReloaderTurbopack( case 'page': { finishBuilding = startBuilding(page, requestUrl) try { - if (globalEntries.app) { + if (globalEntrypoints.app) { const writtenEndpoint = await handleRequireCacheClearing( '_app', - await globalEntries.app.writeToDisk() + await globalEntrypoints.app.writeToDisk() ) processIssues(issues, '_app', writtenEndpoint) } await loadBuildManifest('_app') await loadPagesManifest('_app') - if (globalEntries.document) { + if (globalEntrypoints.document) { const writtenEndpoint = await handleRequireCacheClearing( '_document', - await globalEntries.document.writeToDisk() + await globalEntrypoints.document.writeToDisk() ) processIssues(issues, '_document', writtenEndpoint) } @@ -1096,12 +1096,12 @@ export async function createHotReloaderTurbopack( } } ) - if (globalEntries.document) { + if (globalEntrypoints.document) { changeSubscription( '_document', 'server', false, - globalEntries.document, + globalEntrypoints.document, () => { return { action: HMR_ACTIONS_SENT_TO_BROWSER.RELOAD_PAGE } } @@ -1407,10 +1407,10 @@ export async function createHotReloaderTurbopack( if (page === '/_error') { let finishBuilding = startBuilding(page, requestUrl) try { - if (globalEntries.app) { + if (globalEntrypoints.app) { const writtenEndpoint = await handleRequireCacheClearing( '_app', - await globalEntries.app.writeToDisk() + await globalEntrypoints.app.writeToDisk() ) processIssues(issues, '_app', writtenEndpoint) } @@ -1418,16 +1418,16 @@ export async function createHotReloaderTurbopack( await loadPagesManifest('_app') await loadFontManifest('_app') - if (globalEntries.document) { + if (globalEntrypoints.document) { const writtenEndpoint = await handleRequireCacheClearing( '_document', - await globalEntries.document.writeToDisk() + await globalEntrypoints.document.writeToDisk() ) changeSubscription( '_document', 'server', false, - globalEntries.document, + globalEntrypoints.document, () => { return { action: HMR_ACTIONS_SENT_TO_BROWSER.RELOAD_PAGE } } @@ -1436,10 +1436,10 @@ export async function createHotReloaderTurbopack( } await loadPagesManifest('_document') - if (globalEntries.error) { + if (globalEntrypoints.error) { const writtenEndpoint = await handleRequireCacheClearing( '_error', - await globalEntries.error.writeToDisk() + await globalEntrypoints.error.writeToDisk() ) processIssues(issues, page, writtenEndpoint) } From f7401bbef92bd17880034001bd3e8e251215ad39 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 12 Feb 2024 11:34:38 +0100 Subject: [PATCH 03/12] Update hot-reloader-turbopack.ts --- .../src/server/dev/hot-reloader-turbopack.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/next/src/server/dev/hot-reloader-turbopack.ts b/packages/next/src/server/dev/hot-reloader-turbopack.ts index 790edcbd41888..fb900c26a77bc 100644 --- a/packages/next/src/server/dev/hot-reloader-turbopack.ts +++ b/packages/next/src/server/dev/hot-reloader-turbopack.ts @@ -271,7 +271,7 @@ export async function createHotReloaderTurbopack( serverAddr: `127.0.0.1:${opts.port}`, }) const entrypointsSubscription = project.entrypointsSubscribe() - const currentEntries: Map = new Map() + const currentEntrypoints: Map = new Map() const changeSubscriptions: Map< string, Promise> @@ -626,12 +626,12 @@ export async function createHotReloaderTurbopack( ? (normalizeRewritesForBuildManifest(rewrites) as any) : { afterFiles: [], beforeFiles: [], fallback: [] }, ...Object.fromEntries( - [...currentEntries.keys()].map((pathname) => [ + [...currentEntrypoints.keys()].map((pathname) => [ pathname, `static/chunks/pages${pathname === '/' ? '/index' : pathname}.js`, ]) ), - sortedPages: [...currentEntries.keys()], + sortedPages: [...currentEntrypoints.keys()], } const buildManifestJs = `self.__BUILD_MANIFEST = ${JSON.stringify( content @@ -838,7 +838,7 @@ export async function createHotReloaderTurbopack( globalEntrypoints.document = entrypoints.pagesDocumentEndpoint globalEntrypoints.error = entrypoints.pagesErrorEndpoint - currentEntries.clear() + currentEntrypoints.clear() for (const [pathname, route] of entrypoints.routes) { switch (route.type) { @@ -846,7 +846,7 @@ export async function createHotReloaderTurbopack( case 'page-api': case 'app-page': case 'app-route': { - currentEntries.set(pathname, route) + currentEntrypoints.set(pathname, route) break } default: @@ -861,7 +861,7 @@ export async function createHotReloaderTurbopack( continue } - if (!currentEntries.has(pathname)) { + if (!currentEntrypoints.has(pathname)) { const subscription = await subscriptionPromise subscription.return?.() changeSubscriptions.delete(pathname) @@ -1455,8 +1455,8 @@ export async function createHotReloaderTurbopack( } await currentEntriesHandling const route = - currentEntries.get(page) ?? - currentEntries.get( + currentEntrypoints.get(page) ?? + currentEntrypoints.get( normalizeAppPath( normalizeMetadataRoute(definition?.page ?? inputPage) ) From c788c82c930eaa988a08ccc48a6b0542643da151 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 12 Feb 2024 11:39:47 +0100 Subject: [PATCH 04/12] Update hot-reloader-turbopack.ts --- packages/next/src/server/dev/hot-reloader-turbopack.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/next/src/server/dev/hot-reloader-turbopack.ts b/packages/next/src/server/dev/hot-reloader-turbopack.ts index fb900c26a77bc..9d8b0607fcae0 100644 --- a/packages/next/src/server/dev/hot-reloader-turbopack.ts +++ b/packages/next/src/server/dev/hot-reloader-turbopack.ts @@ -826,7 +826,7 @@ export async function createHotReloaderTurbopack( } try { - async function handleEntries() { + async function handleEntrypointsSubscription() { for await (const entrypoints of entrypointsSubscription) { if (!currentEntriesHandlingResolve) { currentEntriesHandling = new Promise( @@ -990,7 +990,7 @@ export async function createHotReloaderTurbopack( } } - handleEntries().catch((err) => { + handleEntrypointsSubscription().catch((err) => { console.error(err) process.exit(1) }) From 3a9697169233e5eec222ad2af53b4cfbceed269c Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 12 Feb 2024 11:52:58 +0100 Subject: [PATCH 05/12] Remove key as it's constant --- packages/next/src/server/dev/hot-reloader-turbopack.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/next/src/server/dev/hot-reloader-turbopack.ts b/packages/next/src/server/dev/hot-reloader-turbopack.ts index 9d8b0607fcae0..18126d6248c31 100644 --- a/packages/next/src/server/dev/hot-reloader-turbopack.ts +++ b/packages/next/src/server/dev/hot-reloader-turbopack.ts @@ -411,8 +411,8 @@ export async function createHotReloaderTurbopack( } const sendEnqueuedMessagesDebounce = debounce(sendEnqueuedMessages, 2) - function sendHmr(key: string, id: string, payload: HMR_ACTION_TYPES) { - hmrPayloads.set(`${key}:${id}`, payload) + function sendHmr(id: string, payload: HMR_ACTION_TYPES) { + hmrPayloads.set(`${id}`, payload) hmrEventHappened = true sendEnqueuedMessagesDebounce() } @@ -565,7 +565,7 @@ export async function createHotReloaderTurbopack( processIssues(issues, page, change) const payload = await makePayload(page, change) if (payload) { - sendHmr('endpoint-change', key, payload) + sendHmr(key, payload) } } } @@ -875,12 +875,12 @@ export async function createHotReloaderTurbopack( if (prevMiddleware === true && !middleware) { // Went from middleware to no middleware await clearChangeSubscription('middleware', 'server') - sendHmr('entrypoint-change', 'middleware', { + sendHmr('middleware', { event: HMR_ACTIONS_SENT_TO_BROWSER.MIDDLEWARE_CHANGES, }) } else if (prevMiddleware === false && middleware) { // Went from no middleware to middleware - sendHmr('endpoint-change', 'middleware', { + sendHmr('middleware', { event: HMR_ACTIONS_SENT_TO_BROWSER.MIDDLEWARE_CHANGES, }) } From c45e3052ef0f52e1c9d4c68a0ed6325927dc7764 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 12 Feb 2024 12:04:54 +0100 Subject: [PATCH 06/12] Move loadPartialManifest to separate file --- .../src/server/dev/hot-reloader-turbopack.ts | 63 ++++++------------- .../next/src/server/dev/turbopack-utils.ts | 48 ++++++++++++++ 2 files changed, 68 insertions(+), 43 deletions(-) diff --git a/packages/next/src/server/dev/hot-reloader-turbopack.ts b/packages/next/src/server/dev/hot-reloader-turbopack.ts index 18126d6248c31..f6f0919ff80e5 100644 --- a/packages/next/src/server/dev/hot-reloader-turbopack.ts +++ b/packages/next/src/server/dev/hot-reloader-turbopack.ts @@ -86,6 +86,7 @@ import { mergeLoadableManifests, mergeMiddlewareManifests, mergePagesManifests, + readPartialManifest, type TurbopackMiddlewareManifest, } from './turbopack-utils' import { @@ -423,41 +424,6 @@ export async function createHotReloaderTurbopack( sendEnqueuedMessagesDebounce() } - async function loadPartialManifest( - name: - | typeof MIDDLEWARE_MANIFEST - | typeof BUILD_MANIFEST - | typeof APP_BUILD_MANIFEST - | typeof PAGES_MANIFEST - | typeof APP_PATHS_MANIFEST - | `${typeof SERVER_REFERENCE_MANIFEST}.json` - | `${typeof NEXT_FONT_MANIFEST}.json` - | typeof REACT_LOADABLE_MANIFEST, - pageName: string, - type: - | 'pages' - | 'app' - | 'app-route' - | 'middleware' - | 'instrumentation' = 'pages' - ): Promise { - const manifestPath = posix.join( - distDir, - `server`, - type === 'app-route' ? 'app' : type, - type === 'middleware' || type === 'instrumentation' - ? '' - : pageName === '/' - ? 'index' - : pageName === '/index' || pageName.startsWith('/index/') - ? `/index${pageName}` - : pageName, - type === 'app' ? 'page' : type === 'app-route' ? 'route' : '', - name - ) - return JSON.parse(await readFile(posix.join(manifestPath), 'utf-8')) as T - } - const buildManifests = new Map() const appBuildManifests = new Map() const pagesManifests = new Map() @@ -475,7 +441,7 @@ export async function createHotReloaderTurbopack( ): Promise { middlewareManifests.set( pageName, - await loadPartialManifest(MIDDLEWARE_MANIFEST, pageName, type) + await readPartialManifest(distDir, MIDDLEWARE_MANIFEST, pageName, type) ) } @@ -485,21 +451,21 @@ export async function createHotReloaderTurbopack( ): Promise { buildManifests.set( pageName, - await loadPartialManifest(BUILD_MANIFEST, pageName, type) + await readPartialManifest(distDir, BUILD_MANIFEST, pageName, type) ) } async function loadAppBuildManifest(pageName: string): Promise { appBuildManifests.set( pageName, - await loadPartialManifest(APP_BUILD_MANIFEST, pageName, 'app') + await readPartialManifest(distDir, APP_BUILD_MANIFEST, pageName, 'app') ) } async function loadPagesManifest(pageName: string): Promise { pagesManifests.set( pageName, - await loadPartialManifest(PAGES_MANIFEST, pageName) + await readPartialManifest(distDir, PAGES_MANIFEST, pageName) ) } @@ -509,14 +475,15 @@ export async function createHotReloaderTurbopack( ): Promise { appPathsManifests.set( pageName, - await loadPartialManifest(APP_PATHS_MANIFEST, pageName, type) + await readPartialManifest(distDir, APP_PATHS_MANIFEST, pageName, type) ) } async function loadActionManifest(pageName: string): Promise { actionManifests.set( pageName, - await loadPartialManifest( + await readPartialManifest( + distDir, `${SERVER_REFERENCE_MANIFEST}.json`, pageName, 'app' @@ -530,7 +497,12 @@ export async function createHotReloaderTurbopack( ): Promise { fontManifests.set( pageName, - await loadPartialManifest(`${NEXT_FONT_MANIFEST}.json`, pageName, type) + await readPartialManifest( + distDir, + `${NEXT_FONT_MANIFEST}.json`, + pageName, + type + ) ) } @@ -540,7 +512,12 @@ export async function createHotReloaderTurbopack( ): Promise { loadableManifests.set( pageName, - await loadPartialManifest(REACT_LOADABLE_MANIFEST, pageName, type) + await readPartialManifest( + distDir, + REACT_LOADABLE_MANIFEST, + pageName, + type + ) ) } diff --git a/packages/next/src/server/dev/turbopack-utils.ts b/packages/next/src/server/dev/turbopack-utils.ts index 8a5744abb9447..dfb4c9830bcbc 100644 --- a/packages/next/src/server/dev/turbopack-utils.ts +++ b/packages/next/src/server/dev/turbopack-utils.ts @@ -12,6 +12,18 @@ import type { AppBuildManifest } from '../../build/webpack/plugins/app-build-man import type { BuildManifest } from '../get-page-files' import type { NextConfigComplete } from '../config-shared' import loadJsConfig from '../../build/load-jsconfig' +import { posix } from 'path' +import { readFile } from 'fs/promises' +import type { + APP_BUILD_MANIFEST, + APP_PATHS_MANIFEST, + BUILD_MANIFEST, + MIDDLEWARE_MANIFEST, + NEXT_FONT_MANIFEST, + PAGES_MANIFEST, + SERVER_REFERENCE_MANIFEST, + REACT_LOADABLE_MANIFEST, +} from '../../shared/lib/constants' export interface InstrumentationDefinition { files: string[] @@ -179,3 +191,39 @@ export async function getTurbopackJsConfig( const { jsConfig } = await loadJsConfig(dir, nextConfig) return jsConfig ?? { compilerOptions: {} } } + +export async function readPartialManifest( + distDir: string, + name: + | typeof MIDDLEWARE_MANIFEST + | typeof BUILD_MANIFEST + | typeof APP_BUILD_MANIFEST + | typeof PAGES_MANIFEST + | typeof APP_PATHS_MANIFEST + | `${typeof SERVER_REFERENCE_MANIFEST}.json` + | `${typeof NEXT_FONT_MANIFEST}.json` + | typeof REACT_LOADABLE_MANIFEST, + pageName: string, + type: + | 'pages' + | 'app' + | 'app-route' + | 'middleware' + | 'instrumentation' = 'pages' +): Promise { + const manifestPath = posix.join( + distDir, + `server`, + type === 'app-route' ? 'app' : type, + type === 'middleware' || type === 'instrumentation' + ? '' + : pageName === '/' + ? 'index' + : pageName === '/index' || pageName.startsWith('/index/') + ? `/index${pageName}` + : pageName, + type === 'app' ? 'page' : type === 'app-route' ? 'route' : '', + name + ) + return JSON.parse(await readFile(posix.join(manifestPath), 'utf-8')) as T +} From c5d58e31ac1ba9981bf4ca495b6781e49e8a1636 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 12 Feb 2024 13:30:05 +0100 Subject: [PATCH 07/12] Update hot-reloader-turbopack.ts --- .../src/server/dev/hot-reloader-turbopack.ts | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/packages/next/src/server/dev/hot-reloader-turbopack.ts b/packages/next/src/server/dev/hot-reloader-turbopack.ts index f6f0919ff80e5..78cd6c771337f 100644 --- a/packages/next/src/server/dev/hot-reloader-turbopack.ts +++ b/packages/next/src/server/dev/hot-reloader-turbopack.ts @@ -217,6 +217,15 @@ function processIssues( } } +type BuildManifests = Map +type AppBuildManifests = Map +type PagesManifests = Map +type AppPathsManifests = Map +type MiddlewareManifests = Map +type ActionManifests = Map +type FontManifests = Map +type LoadableManifests = Map + export async function createHotReloaderTurbopack( opts: SetupOpts, serverFields: ServerFields, @@ -424,15 +433,20 @@ export async function createHotReloaderTurbopack( sendEnqueuedMessagesDebounce() } - const buildManifests = new Map() - const appBuildManifests = new Map() - const pagesManifests = new Map() - const appPathsManifests = new Map() - const middlewareManifests = new Map() - const actionManifests = new Map() - const fontManifests = new Map() - const loadableManifests = new Map() - const clientToHmrSubscription = new Map>>() + const buildManifests: BuildManifests = new Map() + const appBuildManifests: AppBuildManifests = new Map() + const pagesManifests: PagesManifests = new Map() + const appPathsManifests: AppPathsManifests = new Map() + const middlewareManifests: MiddlewareManifests = new Map() + const actionManifests: ActionManifests = new Map() + const fontManifests: FontManifests = new Map() + const loadableManifests: LoadableManifests = new Map() + + const clientToHmrSubscription: Map< + ws, + Map> + > = new Map() + const clients = new Set() async function loadMiddlewareManifest( From 888a7c8b59e6ba355f6573b2cfa3f31a5ba287f0 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 12 Feb 2024 13:42:33 +0100 Subject: [PATCH 08/12] Update hot-reloader-turbopack.ts --- .../src/server/dev/hot-reloader-turbopack.ts | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/packages/next/src/server/dev/hot-reloader-turbopack.ts b/packages/next/src/server/dev/hot-reloader-turbopack.ts index 78cd6c771337f..94c9a05b09b32 100644 --- a/packages/next/src/server/dev/hot-reloader-turbopack.ts +++ b/packages/next/src/server/dev/hot-reloader-turbopack.ts @@ -188,16 +188,16 @@ function formatIssue(issue: Issue) { return message } -type Issues = Map> +type CurrentIssues = Map> function processIssues( - issues: Issues, + currentIssues: CurrentIssues, name: string, result: TurbopackResult, throwIssue = false ) { const newIssues = new Map() - issues.set(name, newIssues) + currentIssues.set(name, newIssues) const relevantIssues = new Set() @@ -303,7 +303,7 @@ export async function createHotReloaderTurbopack( const hmrPayloads = new Map() const turbopackUpdates: TurbopackUpdate[] = [] - const issues: Issues = new Map() + const currentIssues: CurrentIssues = new Map() const serverPathState = new Map() async function handleRequireCacheClearing( @@ -401,7 +401,7 @@ export async function createHotReloaderTurbopack( let hmrEventHappened = false let hmrHash = 0 const sendEnqueuedMessages = () => { - for (const [, issueMap] of issues) { + for (const [, issueMap] of currentIssues) { if (issueMap.size > 0) { // During compilation errors we want to delay the HMR events until errors are fixed return @@ -553,7 +553,7 @@ export async function createHotReloaderTurbopack( const changed = await changedPromise for await (const change of changed) { - processIssues(issues, page, change) + processIssues(currentIssues, page, change) const payload = await makePayload(page, change) if (payload) { sendHmr(key, payload) @@ -571,7 +571,7 @@ export async function createHotReloaderTurbopack( subscription.return?.() changeSubscriptions.delete(key) } - issues.delete(key) + currentIssues.delete(key) } async function writeBuildManifest( @@ -791,7 +791,7 @@ export async function createHotReloaderTurbopack( await subscription.next() for await (const data of subscription) { - processIssues(issues, id, data) + processIssues(currentIssues, id, data) if (data.type !== 'issues') { sendTurbopackMessage(data) } @@ -888,7 +888,7 @@ export async function createHotReloaderTurbopack( displayName, await instrumentation[prop].writeToDisk() ) - processIssues(issues, name, writtenEndpoint) + processIssues(currentIssues, name, writtenEndpoint) } await processInstrumentation( 'instrumentation (node.js)', @@ -923,7 +923,7 @@ export async function createHotReloaderTurbopack( 'middleware', await middleware.endpoint.writeToDisk() ) - processIssues(issues, 'middleware', writtenEndpoint) + processIssues(currentIssues, 'middleware', writtenEndpoint) await loadMiddlewareManifest('middleware', 'middleware') serverFields.middleware = { match: null as any, @@ -1027,7 +1027,7 @@ export async function createHotReloaderTurbopack( '_app', await globalEntrypoints.app.writeToDisk() ) - processIssues(issues, '_app', writtenEndpoint) + processIssues(currentIssues, '_app', writtenEndpoint) } await loadBuildManifest('_app') await loadPagesManifest('_app') @@ -1037,7 +1037,7 @@ export async function createHotReloaderTurbopack( '_document', await globalEntrypoints.document.writeToDisk() ) - processIssues(issues, '_document', writtenEndpoint) + processIssues(currentIssues, '_document', writtenEndpoint) } await loadPagesManifest('_document') @@ -1060,7 +1060,7 @@ export async function createHotReloaderTurbopack( await writeManifests() - processIssues(issues, page, writtenEndpoint) + processIssues(currentIssues, page, writtenEndpoint) } finally { changeSubscription( page, @@ -1121,7 +1121,7 @@ export async function createHotReloaderTurbopack( await writeManifests() - processIssues(issues, page, writtenEndpoint) + processIssues(currentIssues, page, writtenEndpoint) break } @@ -1166,7 +1166,7 @@ export async function createHotReloaderTurbopack( await loadFontManifest(page, 'app') await writeManifests() - processIssues(issues, page, writtenEndpoint, true) + processIssues(currentIssues, page, writtenEndpoint, true) break } @@ -1188,7 +1188,7 @@ export async function createHotReloaderTurbopack( await writeManifests() - processIssues(issues, page, writtenEndpoint, true) + processIssues(currentIssues, page, writtenEndpoint, true) break } @@ -1315,7 +1315,7 @@ export async function createHotReloaderTurbopack( client.send(JSON.stringify(turbopackConnected)) const errors = [] - for (const pageIssues of issues.values()) { + for (const pageIssues of currentIssues.values()) { for (const issue of pageIssues.values()) { errors.push({ message: formatIssue(issue), @@ -1353,7 +1353,7 @@ export async function createHotReloaderTurbopack( // Not implemented yet. }, async getCompilationErrors(page) { - const thisPageIssues = issues.get(page) + const thisPageIssues = currentIssues.get(page) if (thisPageIssues !== undefined && thisPageIssues.size > 0) { // If there is an error related to the requesting page we display it instead of the first error return [...thisPageIssues.values()].map( @@ -1363,7 +1363,7 @@ export async function createHotReloaderTurbopack( // Otherwise, return all errors across pages const errors = [] - for (const pageIssues of issues.values()) { + for (const pageIssues of currentIssues.values()) { for (const issue of pageIssues.values()) { errors.push(new Error(formatIssue(issue))) } @@ -1403,7 +1403,7 @@ export async function createHotReloaderTurbopack( '_app', await globalEntrypoints.app.writeToDisk() ) - processIssues(issues, '_app', writtenEndpoint) + processIssues(currentIssues, '_app', writtenEndpoint) } await loadBuildManifest('_app') await loadPagesManifest('_app') @@ -1423,7 +1423,7 @@ export async function createHotReloaderTurbopack( return { action: HMR_ACTIONS_SENT_TO_BROWSER.RELOAD_PAGE } } ) - processIssues(issues, '_document', writtenEndpoint) + processIssues(currentIssues, '_document', writtenEndpoint) } await loadPagesManifest('_document') @@ -1432,7 +1432,7 @@ export async function createHotReloaderTurbopack( '_error', await globalEntrypoints.error.writeToDisk() ) - processIssues(issues, page, writtenEndpoint) + processIssues(currentIssues, page, writtenEndpoint) } await loadBuildManifest('_error') await loadPagesManifest('_error') @@ -1487,7 +1487,7 @@ export async function createHotReloaderTurbopack( sendEnqueuedMessages() const errors = new Map() - for (const [, issueMap] of issues) { + for (const [, issueMap] of currentIssues) { for (const [key, issue] of issueMap) { if (errors.has(key)) continue From 326fc4221ba880f9b159d63b5beae2a700ed0c29 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 12 Feb 2024 14:29:47 +0100 Subject: [PATCH 09/12] Consistent name --- packages/next/src/build/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/next/src/build/index.ts b/packages/next/src/build/index.ts index fd515d0866afe..7621532f16fd4 100644 --- a/packages/next/src/build/index.ts +++ b/packages/next/src/build/index.ts @@ -1339,8 +1339,8 @@ export default async function build( }) // eslint-disable-next-line @typescript-eslint/no-unused-vars - const iter = project.entrypointsSubscribe() - // for await (const entrypoints of iter) { + const entrypointsSubscription = project.entrypointsSubscribe() + // for await (const entrypoints of entrypointsSubscription) { // } throw new Error("next build doesn't support turbopack yet") } From 3fead96dc1adaf5e87bf12cba7d9099c28721a13 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 12 Feb 2024 14:34:22 +0100 Subject: [PATCH 10/12] Update hot-reloader-turbopack.ts --- .../src/server/dev/hot-reloader-turbopack.ts | 839 +++++++++++------- 1 file changed, 514 insertions(+), 325 deletions(-) diff --git a/packages/next/src/server/dev/hot-reloader-turbopack.ts b/packages/next/src/server/dev/hot-reloader-turbopack.ts index 94c9a05b09b32..8d1d36ddfda07 100644 --- a/packages/next/src/server/dev/hot-reloader-turbopack.ts +++ b/packages/next/src/server/dev/hot-reloader-turbopack.ts @@ -225,6 +225,347 @@ type MiddlewareManifests = Map type ActionManifests = Map type FontManifests = Map type LoadableManifests = Map +type CurrentEntrypoints = Map + +async function loadMiddlewareManifest( + distDir: string, + middlewareManifests: MiddlewareManifests, + pageName: string, + type: 'pages' | 'app' | 'app-route' | 'middleware' | 'instrumentation' +): Promise { + middlewareManifests.set( + pageName, + await readPartialManifest(distDir, MIDDLEWARE_MANIFEST, pageName, type) + ) +} + +async function loadBuildManifest( + distDir: string, + buildManifests: BuildManifests, + pageName: string, + type: 'app' | 'pages' = 'pages' +): Promise { + buildManifests.set( + pageName, + await readPartialManifest(distDir, BUILD_MANIFEST, pageName, type) + ) +} + +async function loadAppBuildManifest( + distDir: string, + appBuildManifests: AppBuildManifests, + pageName: string +): Promise { + appBuildManifests.set( + pageName, + await readPartialManifest(distDir, APP_BUILD_MANIFEST, pageName, 'app') + ) +} + +async function loadPagesManifest( + distDir: string, + pagesManifests: PagesManifests, + pageName: string +): Promise { + pagesManifests.set( + pageName, + await readPartialManifest(distDir, PAGES_MANIFEST, pageName) + ) +} + +async function loadAppPathManifest( + distDir: string, + appPathsManifests: AppPathsManifests, + pageName: string, + type: 'app' | 'app-route' = 'app' +): Promise { + appPathsManifests.set( + pageName, + await readPartialManifest(distDir, APP_PATHS_MANIFEST, pageName, type) + ) +} + +async function loadActionManifest( + distDir: string, + actionManifests: ActionManifests, + pageName: string +): Promise { + actionManifests.set( + pageName, + await readPartialManifest( + distDir, + `${SERVER_REFERENCE_MANIFEST}.json`, + pageName, + 'app' + ) + ) +} + +async function loadFontManifest( + distDir: string, + fontManifests: FontManifests, + pageName: string, + type: 'app' | 'pages' = 'pages' +): Promise { + fontManifests.set( + pageName, + await readPartialManifest( + distDir, + `${NEXT_FONT_MANIFEST}.json`, + pageName, + type + ) + ) +} + +async function loadLoadableManifest( + distDir: string, + loadableManifests: LoadableManifests, + pageName: string, + type: 'app' | 'pages' = 'pages' +): Promise { + loadableManifests.set( + pageName, + await readPartialManifest(distDir, REACT_LOADABLE_MANIFEST, pageName, type) + ) +} + +async function writeBuildManifest( + distDir: string, + buildManifests: BuildManifests, + currentEntrypoints: CurrentEntrypoints, + rewrites: SetupOpts['fsChecker']['rewrites'] +): Promise { + const buildManifest = mergeBuildManifests(buildManifests.values()) + const buildManifestPath = join(distDir, BUILD_MANIFEST) + const middlewareBuildManifestPath = join( + distDir, + 'server', + `${MIDDLEWARE_BUILD_MANIFEST}.js` + ) + const interceptionRewriteManifestPath = join( + distDir, + 'server', + `${INTERCEPTION_ROUTE_REWRITE_MANIFEST}.js` + ) + deleteCache(buildManifestPath) + deleteCache(middlewareBuildManifestPath) + deleteCache(interceptionRewriteManifestPath) + await writeFileAtomic( + buildManifestPath, + JSON.stringify(buildManifest, null, 2) + ) + await writeFileAtomic( + middlewareBuildManifestPath, + `self.__BUILD_MANIFEST=${JSON.stringify(buildManifest)};` + ) + + const interceptionRewrites = JSON.stringify( + rewrites.beforeFiles.filter(isInterceptionRouteRewrite) + ) + + await writeFileAtomic( + interceptionRewriteManifestPath, + `self.__INTERCEPTION_ROUTE_REWRITE_MANIFEST=${JSON.stringify( + interceptionRewrites + )};` + ) + + const content: ClientBuildManifest = { + __rewrites: rewrites + ? (normalizeRewritesForBuildManifest(rewrites) as any) + : { afterFiles: [], beforeFiles: [], fallback: [] }, + ...Object.fromEntries( + [...currentEntrypoints.keys()].map((pathname) => [ + pathname, + `static/chunks/pages${pathname === '/' ? '/index' : pathname}.js`, + ]) + ), + sortedPages: [...currentEntrypoints.keys()], + } + const buildManifestJs = `self.__BUILD_MANIFEST = ${JSON.stringify( + content + )};self.__BUILD_MANIFEST_CB && self.__BUILD_MANIFEST_CB()` + await writeFileAtomic( + join(distDir, 'static', 'development', '_buildManifest.js'), + buildManifestJs + ) + await writeFileAtomic( + join(distDir, 'static', 'development', '_ssgManifest.js'), + srcEmptySsgManifest + ) +} + +async function writeFallbackBuildManifest( + distDir: string, + buildManifests: BuildManifests +): Promise { + const fallbackBuildManifest = mergeBuildManifests( + [buildManifests.get('_app'), buildManifests.get('_error')].filter( + Boolean + ) as BuildManifest[] + ) + const fallbackBuildManifestPath = join(distDir, `fallback-${BUILD_MANIFEST}`) + deleteCache(fallbackBuildManifestPath) + await writeFileAtomic( + fallbackBuildManifestPath, + JSON.stringify(fallbackBuildManifest, null, 2) + ) +} + +async function writeAppBuildManifest( + distDir: string, + appBuildManifests: AppBuildManifests +): Promise { + const appBuildManifest = mergeAppBuildManifests(appBuildManifests.values()) + const appBuildManifestPath = join(distDir, APP_BUILD_MANIFEST) + deleteCache(appBuildManifestPath) + await writeFileAtomic( + appBuildManifestPath, + JSON.stringify(appBuildManifest, null, 2) + ) +} + +async function writePagesManifest( + distDir: string, + pagesManifests: PagesManifests +): Promise { + const pagesManifest = mergePagesManifests(pagesManifests.values()) + const pagesManifestPath = join(distDir, 'server', PAGES_MANIFEST) + deleteCache(pagesManifestPath) + await writeFileAtomic( + pagesManifestPath, + JSON.stringify(pagesManifest, null, 2) + ) +} + +async function writeAppPathsManifest( + distDir: string, + appPathsManifests: AppPathsManifests +): Promise { + const appPathsManifest = mergePagesManifests(appPathsManifests.values()) + const appPathsManifestPath = join(distDir, 'server', APP_PATHS_MANIFEST) + deleteCache(appPathsManifestPath) + await writeFileAtomic( + appPathsManifestPath, + JSON.stringify(appPathsManifest, null, 2) + ) +} + +async function writeMiddlewareManifest( + distDir: string, + middlewareManifests: MiddlewareManifests +): Promise { + const middlewareManifest = mergeMiddlewareManifests( + middlewareManifests.values() + ) + const middlewareManifestPath = join(distDir, 'server', MIDDLEWARE_MANIFEST) + deleteCache(middlewareManifestPath) + await writeFileAtomic( + middlewareManifestPath, + JSON.stringify(middlewareManifest, null, 2) + ) +} + +async function writeActionManifest( + distDir: string, + actionManifests: ActionManifests +): Promise { + const actionManifest = await mergeActionManifests(actionManifests.values()) + const actionManifestJsonPath = join( + distDir, + 'server', + `${SERVER_REFERENCE_MANIFEST}.json` + ) + const actionManifestJsPath = join( + distDir, + 'server', + `${SERVER_REFERENCE_MANIFEST}.js` + ) + const json = JSON.stringify(actionManifest, null, 2) + deleteCache(actionManifestJsonPath) + deleteCache(actionManifestJsPath) + await writeFile(actionManifestJsonPath, json, 'utf-8') + await writeFile( + actionManifestJsPath, + `self.__RSC_SERVER_MANIFEST=${JSON.stringify(json)}`, + 'utf-8' + ) +} + +async function writeFontManifest( + distDir: string, + fontManifests: FontManifests +): Promise { + const fontManifest = mergeFontManifests(fontManifests.values()) + const json = JSON.stringify(fontManifest, null, 2) + + const fontManifestJsonPath = join( + distDir, + 'server', + `${NEXT_FONT_MANIFEST}.json` + ) + const fontManifestJsPath = join(distDir, 'server', `${NEXT_FONT_MANIFEST}.js`) + deleteCache(fontManifestJsonPath) + deleteCache(fontManifestJsPath) + await writeFileAtomic(fontManifestJsonPath, json) + await writeFileAtomic( + fontManifestJsPath, + `self.__NEXT_FONT_MANIFEST=${JSON.stringify(json)}` + ) +} + +async function writeLoadableManifest( + distDir: string, + loadableManifests: LoadableManifests +): Promise { + const loadableManifest = mergeLoadableManifests(loadableManifests.values()) + const loadableManifestPath = join(distDir, REACT_LOADABLE_MANIFEST) + const middlewareloadableManifestPath = join( + distDir, + 'server', + `${MIDDLEWARE_REACT_LOADABLE_MANIFEST}.js` + ) + + const json = JSON.stringify(loadableManifest, null, 2) + + deleteCache(loadableManifestPath) + deleteCache(middlewareloadableManifestPath) + await writeFileAtomic(loadableManifestPath, json) + await writeFileAtomic( + middlewareloadableManifestPath, + `self.__REACT_LOADABLE_MANIFEST=${JSON.stringify(json)}` + ) +} + +async function writeManifests( + opts: SetupOpts, + distDir: string, + buildManifests: BuildManifests, + appBuildManifests: AppBuildManifests, + pagesManifests: PagesManifests, + appPathsManifests: AppPathsManifests, + middlewareManifests: MiddlewareManifests, + actionManifests: ActionManifests, + fontManifests: FontManifests, + loadableManifests: LoadableManifests, + currentEntrypoints: CurrentEntrypoints +): Promise { + await writeBuildManifest( + distDir, + buildManifests, + currentEntrypoints, + opts.fsChecker.rewrites + ) + await writeAppBuildManifest(distDir, appBuildManifests) + await writePagesManifest(distDir, pagesManifests) + await writeAppPathsManifest(distDir, appPathsManifests) + await writeMiddlewareManifest(distDir, middlewareManifests) + await writeActionManifest(distDir, actionManifests) + await writeFontManifest(distDir, fontManifests) + await writeLoadableManifest(distDir, loadableManifests) + await writeFallbackBuildManifest(distDir, buildManifests) +} export async function createHotReloaderTurbopack( opts: SetupOpts, @@ -281,7 +622,7 @@ export async function createHotReloaderTurbopack( serverAddr: `127.0.0.1:${opts.port}`, }) const entrypointsSubscription = project.entrypointsSubscribe() - const currentEntrypoints: Map = new Map() + const currentEntrypoints: CurrentEntrypoints = new Map() const changeSubscriptions: Map< string, Promise> @@ -449,92 +790,6 @@ export async function createHotReloaderTurbopack( const clients = new Set() - async function loadMiddlewareManifest( - pageName: string, - type: 'pages' | 'app' | 'app-route' | 'middleware' | 'instrumentation' - ): Promise { - middlewareManifests.set( - pageName, - await readPartialManifest(distDir, MIDDLEWARE_MANIFEST, pageName, type) - ) - } - - async function loadBuildManifest( - pageName: string, - type: 'app' | 'pages' = 'pages' - ): Promise { - buildManifests.set( - pageName, - await readPartialManifest(distDir, BUILD_MANIFEST, pageName, type) - ) - } - - async function loadAppBuildManifest(pageName: string): Promise { - appBuildManifests.set( - pageName, - await readPartialManifest(distDir, APP_BUILD_MANIFEST, pageName, 'app') - ) - } - - async function loadPagesManifest(pageName: string): Promise { - pagesManifests.set( - pageName, - await readPartialManifest(distDir, PAGES_MANIFEST, pageName) - ) - } - - async function loadAppPathManifest( - pageName: string, - type: 'app' | 'app-route' = 'app' - ): Promise { - appPathsManifests.set( - pageName, - await readPartialManifest(distDir, APP_PATHS_MANIFEST, pageName, type) - ) - } - - async function loadActionManifest(pageName: string): Promise { - actionManifests.set( - pageName, - await readPartialManifest( - distDir, - `${SERVER_REFERENCE_MANIFEST}.json`, - pageName, - 'app' - ) - ) - } - - async function loadFontManifest( - pageName: string, - type: 'app' | 'pages' = 'pages' - ): Promise { - fontManifests.set( - pageName, - await readPartialManifest( - distDir, - `${NEXT_FONT_MANIFEST}.json`, - pageName, - type - ) - ) - } - - async function loadLoadableManifest( - pageName: string, - type: 'app' | 'pages' = 'pages' - ): Promise { - loadableManifests.set( - pageName, - await readPartialManifest( - distDir, - REACT_LOADABLE_MANIFEST, - pageName, - type - ) - ) - } - async function changeSubscription( page: string, type: 'client' | 'server', @@ -574,206 +829,6 @@ export async function createHotReloaderTurbopack( currentIssues.delete(key) } - async function writeBuildManifest( - rewrites: SetupOpts['fsChecker']['rewrites'] - ): Promise { - const buildManifest = mergeBuildManifests(buildManifests.values()) - const buildManifestPath = join(distDir, BUILD_MANIFEST) - const middlewareBuildManifestPath = join( - distDir, - 'server', - `${MIDDLEWARE_BUILD_MANIFEST}.js` - ) - const interceptionRewriteManifestPath = join( - distDir, - 'server', - `${INTERCEPTION_ROUTE_REWRITE_MANIFEST}.js` - ) - deleteCache(buildManifestPath) - deleteCache(middlewareBuildManifestPath) - deleteCache(interceptionRewriteManifestPath) - await writeFileAtomic( - buildManifestPath, - JSON.stringify(buildManifest, null, 2) - ) - await writeFileAtomic( - middlewareBuildManifestPath, - `self.__BUILD_MANIFEST=${JSON.stringify(buildManifest)};` - ) - - const interceptionRewrites = JSON.stringify( - rewrites.beforeFiles.filter(isInterceptionRouteRewrite) - ) - - await writeFileAtomic( - interceptionRewriteManifestPath, - `self.__INTERCEPTION_ROUTE_REWRITE_MANIFEST=${JSON.stringify( - interceptionRewrites - )};` - ) - - const content: ClientBuildManifest = { - __rewrites: rewrites - ? (normalizeRewritesForBuildManifest(rewrites) as any) - : { afterFiles: [], beforeFiles: [], fallback: [] }, - ...Object.fromEntries( - [...currentEntrypoints.keys()].map((pathname) => [ - pathname, - `static/chunks/pages${pathname === '/' ? '/index' : pathname}.js`, - ]) - ), - sortedPages: [...currentEntrypoints.keys()], - } - const buildManifestJs = `self.__BUILD_MANIFEST = ${JSON.stringify( - content - )};self.__BUILD_MANIFEST_CB && self.__BUILD_MANIFEST_CB()` - await writeFileAtomic( - join(distDir, 'static', 'development', '_buildManifest.js'), - buildManifestJs - ) - await writeFileAtomic( - join(distDir, 'static', 'development', '_ssgManifest.js'), - srcEmptySsgManifest - ) - } - - async function writeFallbackBuildManifest(): Promise { - const fallbackBuildManifest = mergeBuildManifests( - [buildManifests.get('_app'), buildManifests.get('_error')].filter( - Boolean - ) as BuildManifest[] - ) - const fallbackBuildManifestPath = join( - distDir, - `fallback-${BUILD_MANIFEST}` - ) - deleteCache(fallbackBuildManifestPath) - await writeFileAtomic( - fallbackBuildManifestPath, - JSON.stringify(fallbackBuildManifest, null, 2) - ) - } - - async function writeAppBuildManifest(): Promise { - const appBuildManifest = mergeAppBuildManifests(appBuildManifests.values()) - const appBuildManifestPath = join(distDir, APP_BUILD_MANIFEST) - deleteCache(appBuildManifestPath) - await writeFileAtomic( - appBuildManifestPath, - JSON.stringify(appBuildManifest, null, 2) - ) - } - - async function writePagesManifest(): Promise { - const pagesManifest = mergePagesManifests(pagesManifests.values()) - const pagesManifestPath = join(distDir, 'server', PAGES_MANIFEST) - deleteCache(pagesManifestPath) - await writeFileAtomic( - pagesManifestPath, - JSON.stringify(pagesManifest, null, 2) - ) - } - - async function writeAppPathsManifest(): Promise { - const appPathsManifest = mergePagesManifests(appPathsManifests.values()) - const appPathsManifestPath = join(distDir, 'server', APP_PATHS_MANIFEST) - deleteCache(appPathsManifestPath) - await writeFileAtomic( - appPathsManifestPath, - JSON.stringify(appPathsManifest, null, 2) - ) - } - - async function writeMiddlewareManifest(): Promise { - const middlewareManifest = mergeMiddlewareManifests( - middlewareManifests.values() - ) - const middlewareManifestPath = join(distDir, 'server', MIDDLEWARE_MANIFEST) - deleteCache(middlewareManifestPath) - await writeFileAtomic( - middlewareManifestPath, - JSON.stringify(middlewareManifest, null, 2) - ) - } - - async function writeActionManifest(): Promise { - const actionManifest = await mergeActionManifests(actionManifests.values()) - const actionManifestJsonPath = join( - distDir, - 'server', - `${SERVER_REFERENCE_MANIFEST}.json` - ) - const actionManifestJsPath = join( - distDir, - 'server', - `${SERVER_REFERENCE_MANIFEST}.js` - ) - const json = JSON.stringify(actionManifest, null, 2) - deleteCache(actionManifestJsonPath) - deleteCache(actionManifestJsPath) - await writeFile(actionManifestJsonPath, json, 'utf-8') - await writeFile( - actionManifestJsPath, - `self.__RSC_SERVER_MANIFEST=${JSON.stringify(json)}`, - 'utf-8' - ) - } - - async function writeFontManifest(): Promise { - const fontManifest = mergeFontManifests(fontManifests.values()) - const json = JSON.stringify(fontManifest, null, 2) - - const fontManifestJsonPath = join( - distDir, - 'server', - `${NEXT_FONT_MANIFEST}.json` - ) - const fontManifestJsPath = join( - distDir, - 'server', - `${NEXT_FONT_MANIFEST}.js` - ) - deleteCache(fontManifestJsonPath) - deleteCache(fontManifestJsPath) - await writeFileAtomic(fontManifestJsonPath, json) - await writeFileAtomic( - fontManifestJsPath, - `self.__NEXT_FONT_MANIFEST=${JSON.stringify(json)}` - ) - } - - async function writeLoadableManifest(): Promise { - const loadableManifest = mergeLoadableManifests(loadableManifests.values()) - const loadableManifestPath = join(distDir, REACT_LOADABLE_MANIFEST) - const middlewareloadableManifestPath = join( - distDir, - 'server', - `${MIDDLEWARE_REACT_LOADABLE_MANIFEST}.js` - ) - - const json = JSON.stringify(loadableManifest, null, 2) - - deleteCache(loadableManifestPath) - deleteCache(middlewareloadableManifestPath) - await writeFileAtomic(loadableManifestPath, json) - await writeFileAtomic( - middlewareloadableManifestPath, - `self.__REACT_LOADABLE_MANIFEST=${JSON.stringify(json)}` - ) - } - - async function writeManifests(): Promise { - await writeBuildManifest(opts.fsChecker.rewrites) - await writeAppBuildManifest() - await writePagesManifest() - await writeAppPathsManifest() - await writeMiddlewareManifest() - await writeActionManifest() - await writeFontManifest() - await writeLoadableManifest() - await writeFallbackBuildManifest() - } - async function subscribeToHmrEvents(id: string, client: ws) { let mapping = clientToHmrSubscription.get(client) if (mapping === undefined) { @@ -900,8 +955,25 @@ export async function createHotReloaderTurbopack( 'instrumentation.edge', 'edge' ) - await loadMiddlewareManifest('instrumentation', 'instrumentation') - await writeManifests() + await loadMiddlewareManifest( + distDir, + middlewareManifests, + 'instrumentation', + 'instrumentation' + ) + await writeManifests( + opts, + distDir, + buildManifests, + appBuildManifests, + pagesManifests, + appPathsManifests, + middlewareManifests, + actionManifests, + fontManifests, + loadableManifests, + currentEntrypoints + ) serverFields.actualInstrumentationHookFile = '/instrumentation' await propagateServerField( @@ -924,7 +996,12 @@ export async function createHotReloaderTurbopack( await middleware.endpoint.writeToDisk() ) processIssues(currentIssues, 'middleware', writtenEndpoint) - await loadMiddlewareManifest('middleware', 'middleware') + await loadMiddlewareManifest( + distDir, + middlewareManifests, + 'middleware', + 'middleware' + ) serverFields.middleware = { match: null as any, page: '/', @@ -956,7 +1033,19 @@ export async function createHotReloaderTurbopack( 'middleware', serverFields.middleware ) - await writeManifests() + await writeManifests( + opts, + distDir, + buildManifests, + appBuildManifests, + pagesManifests, + appPathsManifests, + middlewareManifests, + actionManifests, + fontManifests, + loadableManifests, + currentEntrypoints + ) finishBuilding() return { event: HMR_ACTIONS_SENT_TO_BROWSER.MIDDLEWARE_CHANGES } @@ -1003,8 +1092,19 @@ export async function createHotReloaderTurbopack( ) ) await currentEntriesHandling - await writeManifests() - + await writeManifests( + opts, + distDir, + buildManifests, + appBuildManifests, + pagesManifests, + appPathsManifests, + middlewareManifests, + actionManifests, + fontManifests, + loadableManifests, + currentEntrypoints + ) const overlayMiddleware = getOverlayMiddleware(project) const versionInfo: VersionInfo = await getVersionInfo( isTestMode || opts.telemetry.isEnabled @@ -1029,8 +1129,8 @@ export async function createHotReloaderTurbopack( ) processIssues(currentIssues, '_app', writtenEndpoint) } - await loadBuildManifest('_app') - await loadPagesManifest('_app') + await loadBuildManifest(distDir, buildManifests, '_app') + await loadPagesManifest(distDir, pagesManifests, '_app') if (globalEntrypoints.document) { const writtenEndpoint = await handleRequireCacheClearing( @@ -1039,7 +1139,7 @@ export async function createHotReloaderTurbopack( ) processIssues(currentIssues, '_document', writtenEndpoint) } - await loadPagesManifest('_document') + await loadPagesManifest(distDir, pagesManifests, '_document') const writtenEndpoint = await handleRequireCacheClearing( page, @@ -1048,17 +1148,39 @@ export async function createHotReloaderTurbopack( const type = writtenEndpoint?.type - await loadBuildManifest(page) - await loadPagesManifest(page) + await loadBuildManifest(distDir, buildManifests, page) + await loadPagesManifest(distDir, pagesManifests, page) if (type === 'edge') { - await loadMiddlewareManifest(page, 'pages') + await loadMiddlewareManifest( + distDir, + middlewareManifests, + page, + 'pages' + ) } else { middlewareManifests.delete(page) } - await loadFontManifest(page, 'pages') - await loadLoadableManifest(page, 'pages') + await loadFontManifest(distDir, fontManifests, page, 'pages') + await loadLoadableManifest( + distDir, + loadableManifests, + page, + 'pages' + ) - await writeManifests() + await writeManifests( + opts, + distDir, + buildManifests, + appBuildManifests, + pagesManifests, + appPathsManifests, + middlewareManifests, + actionManifests, + fontManifests, + loadableManifests, + currentEntrypoints + ) processIssues(currentIssues, page, writtenEndpoint) } finally { @@ -1111,15 +1233,32 @@ export async function createHotReloaderTurbopack( const type = writtenEndpoint?.type - await loadPagesManifest(page) + await loadPagesManifest(distDir, pagesManifests, page) if (type === 'edge') { - await loadMiddlewareManifest(page, 'pages') + await loadMiddlewareManifest( + distDir, + middlewareManifests, + page, + 'pages' + ) } else { middlewareManifests.delete(page) } - await loadLoadableManifest(page, 'pages') + await loadLoadableManifest(distDir, loadableManifests, page, 'pages') - await writeManifests() + await writeManifests( + opts, + distDir, + buildManifests, + appBuildManifests, + pagesManifests, + appPathsManifests, + middlewareManifests, + actionManifests, + fontManifests, + loadableManifests, + currentEntrypoints + ) processIssues(currentIssues, page, writtenEndpoint) @@ -1154,17 +1293,34 @@ export async function createHotReloaderTurbopack( const type = writtenEndpoint?.type if (type === 'edge') { - await loadMiddlewareManifest(page, 'app') + await loadMiddlewareManifest( + distDir, + middlewareManifests, + page, + 'app' + ) } else { middlewareManifests.delete(page) } - await loadAppBuildManifest(page) - await loadBuildManifest(page, 'app') - await loadAppPathManifest(page, 'app') - await loadActionManifest(page) - await loadFontManifest(page, 'app') - await writeManifests() + await loadAppBuildManifest(distDir, appBuildManifests, page) + await loadBuildManifest(distDir, buildManifests, page, 'app') + await loadAppPathManifest(distDir, appPathsManifests, page, 'app') + await loadActionManifest(distDir, actionManifests, page) + await loadFontManifest(distDir, fontManifests, page, 'app') + await writeManifests( + opts, + distDir, + buildManifests, + appBuildManifests, + pagesManifests, + appPathsManifests, + middlewareManifests, + actionManifests, + fontManifests, + loadableManifests, + currentEntrypoints + ) processIssues(currentIssues, page, writtenEndpoint, true) @@ -1179,15 +1335,36 @@ export async function createHotReloaderTurbopack( const type = writtenEndpoint?.type - await loadAppPathManifest(page, 'app-route') + await loadAppPathManifest( + distDir, + appPathsManifests, + page, + 'app-route' + ) if (type === 'edge') { - await loadMiddlewareManifest(page, 'app-route') + await loadMiddlewareManifest( + distDir, + middlewareManifests, + page, + 'app-route' + ) } else { middlewareManifests.delete(page) } - await writeManifests() - + await writeManifests( + opts, + distDir, + buildManifests, + appBuildManifests, + pagesManifests, + appPathsManifests, + middlewareManifests, + actionManifests, + fontManifests, + loadableManifests, + currentEntrypoints + ) processIssues(currentIssues, page, writtenEndpoint, true) break @@ -1405,9 +1582,9 @@ export async function createHotReloaderTurbopack( ) processIssues(currentIssues, '_app', writtenEndpoint) } - await loadBuildManifest('_app') - await loadPagesManifest('_app') - await loadFontManifest('_app') + await loadBuildManifest(distDir, buildManifests, '_app') + await loadPagesManifest(distDir, pagesManifests, '_app') + await loadFontManifest(distDir, fontManifests, '_app') if (globalEntrypoints.document) { const writtenEndpoint = await handleRequireCacheClearing( @@ -1425,7 +1602,7 @@ export async function createHotReloaderTurbopack( ) processIssues(currentIssues, '_document', writtenEndpoint) } - await loadPagesManifest('_document') + await loadPagesManifest(distDir, pagesManifests, '_document') if (globalEntrypoints.error) { const writtenEndpoint = await handleRequireCacheClearing( @@ -1434,11 +1611,23 @@ export async function createHotReloaderTurbopack( ) processIssues(currentIssues, page, writtenEndpoint) } - await loadBuildManifest('_error') - await loadPagesManifest('_error') - await loadFontManifest('_error') + await loadBuildManifest(distDir, buildManifests, '_error') + await loadPagesManifest(distDir, pagesManifests, '_error') + await loadFontManifest(distDir, fontManifests, '_error') - await writeManifests() + await writeManifests( + opts, + distDir, + buildManifests, + appBuildManifests, + pagesManifests, + appPathsManifests, + middlewareManifests, + actionManifests, + fontManifests, + loadableManifests, + currentEntrypoints + ) } finally { finishBuilding() } From 969f8c89dadfefcec268460cce27bd73eb3ae64c Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 12 Feb 2024 14:45:53 +0100 Subject: [PATCH 11/12] Fix lint --- packages/next/src/server/dev/hot-reloader-turbopack.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/next/src/server/dev/hot-reloader-turbopack.ts b/packages/next/src/server/dev/hot-reloader-turbopack.ts index 8d1d36ddfda07..80ea2dc6e3694 100644 --- a/packages/next/src/server/dev/hot-reloader-turbopack.ts +++ b/packages/next/src/server/dev/hot-reloader-turbopack.ts @@ -22,7 +22,7 @@ import type { import ws from 'next/dist/compiled/ws' import { createDefineEnv } from '../../build/swc' -import { join, posix } from 'path' +import { join } from 'path' import * as Log from '../../build/output/log' import { getVersionInfo, @@ -46,7 +46,7 @@ import { INTERCEPTION_ROUTE_REWRITE_MANIFEST, } from '../../shared/lib/constants' import { getOverlayMiddleware } from 'next/dist/compiled/@next/react-dev-overlay/dist/middleware-turbopack' -import { mkdir, readFile, writeFile } from 'fs/promises' +import { mkdir, writeFile } from 'fs/promises' import { PageNotFoundError } from '../../shared/lib/utils' import { type ClientBuildManifest, From 1e8fe9a1d363c73fe565f4bf8c3dd0f3274c2926 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 12 Feb 2024 15:01:21 +0100 Subject: [PATCH 12/12] Move functions to turbopack-utils --- .../src/server/dev/hot-reloader-turbopack.ts | 404 +----------------- .../next/src/server/dev/turbopack-utils.ts | 369 +++++++++++++++- 2 files changed, 384 insertions(+), 389 deletions(-) diff --git a/packages/next/src/server/dev/hot-reloader-turbopack.ts b/packages/next/src/server/dev/hot-reloader-turbopack.ts index 80ea2dc6e3694..1848ffe7cd05d 100644 --- a/packages/next/src/server/dev/hot-reloader-turbopack.ts +++ b/packages/next/src/server/dev/hot-reloader-turbopack.ts @@ -8,9 +8,6 @@ import type { } from '../../build/swc' import type { Socket } from 'net' import type { OutputState } from '../../build/output/store' -import type { BuildManifest } from '../get-page-files' -import type { PagesManifest } from '../../build/webpack/plugins/pages-manifest-plugin' -import type { AppBuildManifest } from '../../build/webpack/plugins/app-build-manifest-plugin' import type { CompilationError, HMR_ACTION_TYPES, @@ -29,30 +26,10 @@ import { matchNextPageBundleRequest, } from './hot-reloader-webpack' import { normalizeAppPath } from '../../shared/lib/router/utils/app-paths' -import { isInterceptionRouteRewrite } from '../../lib/generate-interception-routes-rewrites' import { store as consoleStore } from '../../build/output/store' - -import { - APP_BUILD_MANIFEST, - APP_PATHS_MANIFEST, - BUILD_MANIFEST, - MIDDLEWARE_MANIFEST, - NEXT_FONT_MANIFEST, - PAGES_MANIFEST, - SERVER_REFERENCE_MANIFEST, - REACT_LOADABLE_MANIFEST, - MIDDLEWARE_REACT_LOADABLE_MANIFEST, - MIDDLEWARE_BUILD_MANIFEST, - INTERCEPTION_ROUTE_REWRITE_MANIFEST, -} from '../../shared/lib/constants' import { getOverlayMiddleware } from 'next/dist/compiled/@next/react-dev-overlay/dist/middleware-turbopack' import { mkdir, writeFile } from 'fs/promises' import { PageNotFoundError } from '../../shared/lib/utils' -import { - type ClientBuildManifest, - normalizeRewritesForBuildManifest, - srcEmptySsgManifest, -} from '../../build/webpack/plugins/build-manifest-plugin' import { HMR_ACTIONS_SENT_TO_BROWSER } from './hot-reloader-types' import type { Update as TurbopackUpdate } from '../../build/swc' import { debounce } from '../utils' @@ -65,29 +42,34 @@ import { clearModuleContext, clearAllModuleContexts, } from '../lib/render-server' -import type { ActionManifest } from '../../build/webpack/plugins/flight-client-entry-plugin' import { denormalizePagePath } from '../../shared/lib/page-path/denormalize-page-path' -import type { LoadableManifest } from '../load-components' import { bold, green, magenta, red } from '../../lib/picocolors' -import { writeFileAtomic } from '../../lib/fs/write-atomic' import { trace } from '../../trace' import type { VersionInfo } from './parse-version-info' -import type { NextFontManifest } from '../../build/webpack/plugins/next-font-manifest-plugin' import { MAGIC_IDENTIFIER_REGEX, decodeMagicIdentifier, } from '../../shared/lib/magic-identifier' import { getTurbopackJsConfig, - mergeActionManifests, - mergeAppBuildManifests, - mergeBuildManifests, - mergeFontManifests, - mergeLoadableManifests, - mergeMiddlewareManifests, - mergePagesManifests, - readPartialManifest, - type TurbopackMiddlewareManifest, + type BuildManifests, + type AppBuildManifests, + type PagesManifests, + type AppPathsManifests, + type MiddlewareManifests, + type ActionManifests, + type FontManifests, + type LoadableManifests, + loadMiddlewareManifest, + writeManifests, + loadBuildManifest, + loadPagesManifest, + loadLoadableManifest, + loadFontManifest, + loadAppBuildManifest, + loadAppPathManifest, + loadActionManifest, + type CurrentEntrypoints, } from './turbopack-utils' import { propagateServerField, @@ -217,356 +199,6 @@ function processIssues( } } -type BuildManifests = Map -type AppBuildManifests = Map -type PagesManifests = Map -type AppPathsManifests = Map -type MiddlewareManifests = Map -type ActionManifests = Map -type FontManifests = Map -type LoadableManifests = Map -type CurrentEntrypoints = Map - -async function loadMiddlewareManifest( - distDir: string, - middlewareManifests: MiddlewareManifests, - pageName: string, - type: 'pages' | 'app' | 'app-route' | 'middleware' | 'instrumentation' -): Promise { - middlewareManifests.set( - pageName, - await readPartialManifest(distDir, MIDDLEWARE_MANIFEST, pageName, type) - ) -} - -async function loadBuildManifest( - distDir: string, - buildManifests: BuildManifests, - pageName: string, - type: 'app' | 'pages' = 'pages' -): Promise { - buildManifests.set( - pageName, - await readPartialManifest(distDir, BUILD_MANIFEST, pageName, type) - ) -} - -async function loadAppBuildManifest( - distDir: string, - appBuildManifests: AppBuildManifests, - pageName: string -): Promise { - appBuildManifests.set( - pageName, - await readPartialManifest(distDir, APP_BUILD_MANIFEST, pageName, 'app') - ) -} - -async function loadPagesManifest( - distDir: string, - pagesManifests: PagesManifests, - pageName: string -): Promise { - pagesManifests.set( - pageName, - await readPartialManifest(distDir, PAGES_MANIFEST, pageName) - ) -} - -async function loadAppPathManifest( - distDir: string, - appPathsManifests: AppPathsManifests, - pageName: string, - type: 'app' | 'app-route' = 'app' -): Promise { - appPathsManifests.set( - pageName, - await readPartialManifest(distDir, APP_PATHS_MANIFEST, pageName, type) - ) -} - -async function loadActionManifest( - distDir: string, - actionManifests: ActionManifests, - pageName: string -): Promise { - actionManifests.set( - pageName, - await readPartialManifest( - distDir, - `${SERVER_REFERENCE_MANIFEST}.json`, - pageName, - 'app' - ) - ) -} - -async function loadFontManifest( - distDir: string, - fontManifests: FontManifests, - pageName: string, - type: 'app' | 'pages' = 'pages' -): Promise { - fontManifests.set( - pageName, - await readPartialManifest( - distDir, - `${NEXT_FONT_MANIFEST}.json`, - pageName, - type - ) - ) -} - -async function loadLoadableManifest( - distDir: string, - loadableManifests: LoadableManifests, - pageName: string, - type: 'app' | 'pages' = 'pages' -): Promise { - loadableManifests.set( - pageName, - await readPartialManifest(distDir, REACT_LOADABLE_MANIFEST, pageName, type) - ) -} - -async function writeBuildManifest( - distDir: string, - buildManifests: BuildManifests, - currentEntrypoints: CurrentEntrypoints, - rewrites: SetupOpts['fsChecker']['rewrites'] -): Promise { - const buildManifest = mergeBuildManifests(buildManifests.values()) - const buildManifestPath = join(distDir, BUILD_MANIFEST) - const middlewareBuildManifestPath = join( - distDir, - 'server', - `${MIDDLEWARE_BUILD_MANIFEST}.js` - ) - const interceptionRewriteManifestPath = join( - distDir, - 'server', - `${INTERCEPTION_ROUTE_REWRITE_MANIFEST}.js` - ) - deleteCache(buildManifestPath) - deleteCache(middlewareBuildManifestPath) - deleteCache(interceptionRewriteManifestPath) - await writeFileAtomic( - buildManifestPath, - JSON.stringify(buildManifest, null, 2) - ) - await writeFileAtomic( - middlewareBuildManifestPath, - `self.__BUILD_MANIFEST=${JSON.stringify(buildManifest)};` - ) - - const interceptionRewrites = JSON.stringify( - rewrites.beforeFiles.filter(isInterceptionRouteRewrite) - ) - - await writeFileAtomic( - interceptionRewriteManifestPath, - `self.__INTERCEPTION_ROUTE_REWRITE_MANIFEST=${JSON.stringify( - interceptionRewrites - )};` - ) - - const content: ClientBuildManifest = { - __rewrites: rewrites - ? (normalizeRewritesForBuildManifest(rewrites) as any) - : { afterFiles: [], beforeFiles: [], fallback: [] }, - ...Object.fromEntries( - [...currentEntrypoints.keys()].map((pathname) => [ - pathname, - `static/chunks/pages${pathname === '/' ? '/index' : pathname}.js`, - ]) - ), - sortedPages: [...currentEntrypoints.keys()], - } - const buildManifestJs = `self.__BUILD_MANIFEST = ${JSON.stringify( - content - )};self.__BUILD_MANIFEST_CB && self.__BUILD_MANIFEST_CB()` - await writeFileAtomic( - join(distDir, 'static', 'development', '_buildManifest.js'), - buildManifestJs - ) - await writeFileAtomic( - join(distDir, 'static', 'development', '_ssgManifest.js'), - srcEmptySsgManifest - ) -} - -async function writeFallbackBuildManifest( - distDir: string, - buildManifests: BuildManifests -): Promise { - const fallbackBuildManifest = mergeBuildManifests( - [buildManifests.get('_app'), buildManifests.get('_error')].filter( - Boolean - ) as BuildManifest[] - ) - const fallbackBuildManifestPath = join(distDir, `fallback-${BUILD_MANIFEST}`) - deleteCache(fallbackBuildManifestPath) - await writeFileAtomic( - fallbackBuildManifestPath, - JSON.stringify(fallbackBuildManifest, null, 2) - ) -} - -async function writeAppBuildManifest( - distDir: string, - appBuildManifests: AppBuildManifests -): Promise { - const appBuildManifest = mergeAppBuildManifests(appBuildManifests.values()) - const appBuildManifestPath = join(distDir, APP_BUILD_MANIFEST) - deleteCache(appBuildManifestPath) - await writeFileAtomic( - appBuildManifestPath, - JSON.stringify(appBuildManifest, null, 2) - ) -} - -async function writePagesManifest( - distDir: string, - pagesManifests: PagesManifests -): Promise { - const pagesManifest = mergePagesManifests(pagesManifests.values()) - const pagesManifestPath = join(distDir, 'server', PAGES_MANIFEST) - deleteCache(pagesManifestPath) - await writeFileAtomic( - pagesManifestPath, - JSON.stringify(pagesManifest, null, 2) - ) -} - -async function writeAppPathsManifest( - distDir: string, - appPathsManifests: AppPathsManifests -): Promise { - const appPathsManifest = mergePagesManifests(appPathsManifests.values()) - const appPathsManifestPath = join(distDir, 'server', APP_PATHS_MANIFEST) - deleteCache(appPathsManifestPath) - await writeFileAtomic( - appPathsManifestPath, - JSON.stringify(appPathsManifest, null, 2) - ) -} - -async function writeMiddlewareManifest( - distDir: string, - middlewareManifests: MiddlewareManifests -): Promise { - const middlewareManifest = mergeMiddlewareManifests( - middlewareManifests.values() - ) - const middlewareManifestPath = join(distDir, 'server', MIDDLEWARE_MANIFEST) - deleteCache(middlewareManifestPath) - await writeFileAtomic( - middlewareManifestPath, - JSON.stringify(middlewareManifest, null, 2) - ) -} - -async function writeActionManifest( - distDir: string, - actionManifests: ActionManifests -): Promise { - const actionManifest = await mergeActionManifests(actionManifests.values()) - const actionManifestJsonPath = join( - distDir, - 'server', - `${SERVER_REFERENCE_MANIFEST}.json` - ) - const actionManifestJsPath = join( - distDir, - 'server', - `${SERVER_REFERENCE_MANIFEST}.js` - ) - const json = JSON.stringify(actionManifest, null, 2) - deleteCache(actionManifestJsonPath) - deleteCache(actionManifestJsPath) - await writeFile(actionManifestJsonPath, json, 'utf-8') - await writeFile( - actionManifestJsPath, - `self.__RSC_SERVER_MANIFEST=${JSON.stringify(json)}`, - 'utf-8' - ) -} - -async function writeFontManifest( - distDir: string, - fontManifests: FontManifests -): Promise { - const fontManifest = mergeFontManifests(fontManifests.values()) - const json = JSON.stringify(fontManifest, null, 2) - - const fontManifestJsonPath = join( - distDir, - 'server', - `${NEXT_FONT_MANIFEST}.json` - ) - const fontManifestJsPath = join(distDir, 'server', `${NEXT_FONT_MANIFEST}.js`) - deleteCache(fontManifestJsonPath) - deleteCache(fontManifestJsPath) - await writeFileAtomic(fontManifestJsonPath, json) - await writeFileAtomic( - fontManifestJsPath, - `self.__NEXT_FONT_MANIFEST=${JSON.stringify(json)}` - ) -} - -async function writeLoadableManifest( - distDir: string, - loadableManifests: LoadableManifests -): Promise { - const loadableManifest = mergeLoadableManifests(loadableManifests.values()) - const loadableManifestPath = join(distDir, REACT_LOADABLE_MANIFEST) - const middlewareloadableManifestPath = join( - distDir, - 'server', - `${MIDDLEWARE_REACT_LOADABLE_MANIFEST}.js` - ) - - const json = JSON.stringify(loadableManifest, null, 2) - - deleteCache(loadableManifestPath) - deleteCache(middlewareloadableManifestPath) - await writeFileAtomic(loadableManifestPath, json) - await writeFileAtomic( - middlewareloadableManifestPath, - `self.__REACT_LOADABLE_MANIFEST=${JSON.stringify(json)}` - ) -} - -async function writeManifests( - opts: SetupOpts, - distDir: string, - buildManifests: BuildManifests, - appBuildManifests: AppBuildManifests, - pagesManifests: PagesManifests, - appPathsManifests: AppPathsManifests, - middlewareManifests: MiddlewareManifests, - actionManifests: ActionManifests, - fontManifests: FontManifests, - loadableManifests: LoadableManifests, - currentEntrypoints: CurrentEntrypoints -): Promise { - await writeBuildManifest( - distDir, - buildManifests, - currentEntrypoints, - opts.fsChecker.rewrites - ) - await writeAppBuildManifest(distDir, appBuildManifests) - await writePagesManifest(distDir, pagesManifests) - await writeAppPathsManifest(distDir, appPathsManifests) - await writeMiddlewareManifest(distDir, middlewareManifests) - await writeActionManifest(distDir, actionManifests) - await writeFontManifest(distDir, fontManifests) - await writeLoadableManifest(distDir, loadableManifests) - await writeFallbackBuildManifest(distDir, buildManifests) -} - export async function createHotReloaderTurbopack( opts: SetupOpts, serverFields: ServerFields, diff --git a/packages/next/src/server/dev/turbopack-utils.ts b/packages/next/src/server/dev/turbopack-utils.ts index dfb4c9830bcbc..42ff28ac12766 100644 --- a/packages/next/src/server/dev/turbopack-utils.ts +++ b/packages/next/src/server/dev/turbopack-utils.ts @@ -12,9 +12,9 @@ import type { AppBuildManifest } from '../../build/webpack/plugins/app-build-man import type { BuildManifest } from '../get-page-files' import type { NextConfigComplete } from '../config-shared' import loadJsConfig from '../../build/load-jsconfig' -import { posix } from 'path' -import { readFile } from 'fs/promises' -import type { +import { join, posix } from 'path' +import { readFile, writeFile } from 'fs/promises' +import { APP_BUILD_MANIFEST, APP_PATHS_MANIFEST, BUILD_MANIFEST, @@ -23,7 +23,20 @@ import type { PAGES_MANIFEST, SERVER_REFERENCE_MANIFEST, REACT_LOADABLE_MANIFEST, + MIDDLEWARE_BUILD_MANIFEST, + INTERCEPTION_ROUTE_REWRITE_MANIFEST, + MIDDLEWARE_REACT_LOADABLE_MANIFEST, } from '../../shared/lib/constants' +import { writeFileAtomic } from '../../lib/fs/write-atomic' +import { deleteCache } from '../../build/webpack/plugins/nextjs-require-cache-hot-reloader' +import { + normalizeRewritesForBuildManifest, + type ClientBuildManifest, + srcEmptySsgManifest, +} from '../../build/webpack/plugins/build-manifest-plugin' +import type { SetupOpts } from '../lib/router-utils/setup-dev-bundler' +import { isInterceptionRouteRewrite } from '../../lib/generate-interception-routes-rewrites' +import type { Route } from '../../build/swc' export interface InstrumentationDefinition { files: string[] @@ -227,3 +240,353 @@ export async function readPartialManifest( ) return JSON.parse(await readFile(posix.join(manifestPath), 'utf-8')) as T } + +export type BuildManifests = Map +export type AppBuildManifests = Map +export type PagesManifests = Map +export type AppPathsManifests = Map +export type MiddlewareManifests = Map +export type ActionManifests = Map +export type FontManifests = Map +export type LoadableManifests = Map +export type CurrentEntrypoints = Map + +export async function loadMiddlewareManifest( + distDir: string, + middlewareManifests: MiddlewareManifests, + pageName: string, + type: 'pages' | 'app' | 'app-route' | 'middleware' | 'instrumentation' +): Promise { + middlewareManifests.set( + pageName, + await readPartialManifest(distDir, MIDDLEWARE_MANIFEST, pageName, type) + ) +} + +export async function loadBuildManifest( + distDir: string, + buildManifests: BuildManifests, + pageName: string, + type: 'app' | 'pages' = 'pages' +): Promise { + buildManifests.set( + pageName, + await readPartialManifest(distDir, BUILD_MANIFEST, pageName, type) + ) +} + +export async function loadAppBuildManifest( + distDir: string, + appBuildManifests: AppBuildManifests, + pageName: string +): Promise { + appBuildManifests.set( + pageName, + await readPartialManifest(distDir, APP_BUILD_MANIFEST, pageName, 'app') + ) +} + +export async function loadPagesManifest( + distDir: string, + pagesManifests: PagesManifests, + pageName: string +): Promise { + pagesManifests.set( + pageName, + await readPartialManifest(distDir, PAGES_MANIFEST, pageName) + ) +} + +export async function loadAppPathManifest( + distDir: string, + appPathsManifests: AppPathsManifests, + pageName: string, + type: 'app' | 'app-route' = 'app' +): Promise { + appPathsManifests.set( + pageName, + await readPartialManifest(distDir, APP_PATHS_MANIFEST, pageName, type) + ) +} + +export async function loadActionManifest( + distDir: string, + actionManifests: ActionManifests, + pageName: string +): Promise { + actionManifests.set( + pageName, + await readPartialManifest( + distDir, + `${SERVER_REFERENCE_MANIFEST}.json`, + pageName, + 'app' + ) + ) +} + +export async function loadFontManifest( + distDir: string, + fontManifests: FontManifests, + pageName: string, + type: 'app' | 'pages' = 'pages' +): Promise { + fontManifests.set( + pageName, + await readPartialManifest( + distDir, + `${NEXT_FONT_MANIFEST}.json`, + pageName, + type + ) + ) +} + +export async function loadLoadableManifest( + distDir: string, + loadableManifests: LoadableManifests, + pageName: string, + type: 'app' | 'pages' = 'pages' +): Promise { + loadableManifests.set( + pageName, + await readPartialManifest(distDir, REACT_LOADABLE_MANIFEST, pageName, type) + ) +} + +async function writeBuildManifest( + distDir: string, + buildManifests: BuildManifests, + currentEntrypoints: CurrentEntrypoints, + rewrites: SetupOpts['fsChecker']['rewrites'] +): Promise { + const buildManifest = mergeBuildManifests(buildManifests.values()) + const buildManifestPath = join(distDir, BUILD_MANIFEST) + const middlewareBuildManifestPath = join( + distDir, + 'server', + `${MIDDLEWARE_BUILD_MANIFEST}.js` + ) + const interceptionRewriteManifestPath = join( + distDir, + 'server', + `${INTERCEPTION_ROUTE_REWRITE_MANIFEST}.js` + ) + deleteCache(buildManifestPath) + deleteCache(middlewareBuildManifestPath) + deleteCache(interceptionRewriteManifestPath) + await writeFileAtomic( + buildManifestPath, + JSON.stringify(buildManifest, null, 2) + ) + await writeFileAtomic( + middlewareBuildManifestPath, + `self.__BUILD_MANIFEST=${JSON.stringify(buildManifest)};` + ) + + const interceptionRewrites = JSON.stringify( + rewrites.beforeFiles.filter(isInterceptionRouteRewrite) + ) + + await writeFileAtomic( + interceptionRewriteManifestPath, + `self.__INTERCEPTION_ROUTE_REWRITE_MANIFEST=${JSON.stringify( + interceptionRewrites + )};` + ) + + const content: ClientBuildManifest = { + __rewrites: rewrites + ? (normalizeRewritesForBuildManifest(rewrites) as any) + : { afterFiles: [], beforeFiles: [], fallback: [] }, + ...Object.fromEntries( + [...currentEntrypoints.keys()].map((pathname) => [ + pathname, + `static/chunks/pages${pathname === '/' ? '/index' : pathname}.js`, + ]) + ), + sortedPages: [...currentEntrypoints.keys()], + } + const buildManifestJs = `self.__BUILD_MANIFEST = ${JSON.stringify( + content + )};self.__BUILD_MANIFEST_CB && self.__BUILD_MANIFEST_CB()` + await writeFileAtomic( + join(distDir, 'static', 'development', '_buildManifest.js'), + buildManifestJs + ) + await writeFileAtomic( + join(distDir, 'static', 'development', '_ssgManifest.js'), + srcEmptySsgManifest + ) +} + +async function writeFallbackBuildManifest( + distDir: string, + buildManifests: BuildManifests +): Promise { + const fallbackBuildManifest = mergeBuildManifests( + [buildManifests.get('_app'), buildManifests.get('_error')].filter( + Boolean + ) as BuildManifest[] + ) + const fallbackBuildManifestPath = join(distDir, `fallback-${BUILD_MANIFEST}`) + deleteCache(fallbackBuildManifestPath) + await writeFileAtomic( + fallbackBuildManifestPath, + JSON.stringify(fallbackBuildManifest, null, 2) + ) +} + +async function writeAppBuildManifest( + distDir: string, + appBuildManifests: AppBuildManifests +): Promise { + const appBuildManifest = mergeAppBuildManifests(appBuildManifests.values()) + const appBuildManifestPath = join(distDir, APP_BUILD_MANIFEST) + deleteCache(appBuildManifestPath) + await writeFileAtomic( + appBuildManifestPath, + JSON.stringify(appBuildManifest, null, 2) + ) +} + +async function writePagesManifest( + distDir: string, + pagesManifests: PagesManifests +): Promise { + const pagesManifest = mergePagesManifests(pagesManifests.values()) + const pagesManifestPath = join(distDir, 'server', PAGES_MANIFEST) + deleteCache(pagesManifestPath) + await writeFileAtomic( + pagesManifestPath, + JSON.stringify(pagesManifest, null, 2) + ) +} + +async function writeAppPathsManifest( + distDir: string, + appPathsManifests: AppPathsManifests +): Promise { + const appPathsManifest = mergePagesManifests(appPathsManifests.values()) + const appPathsManifestPath = join(distDir, 'server', APP_PATHS_MANIFEST) + deleteCache(appPathsManifestPath) + await writeFileAtomic( + appPathsManifestPath, + JSON.stringify(appPathsManifest, null, 2) + ) +} + +async function writeMiddlewareManifest( + distDir: string, + middlewareManifests: MiddlewareManifests +): Promise { + const middlewareManifest = mergeMiddlewareManifests( + middlewareManifests.values() + ) + const middlewareManifestPath = join(distDir, 'server', MIDDLEWARE_MANIFEST) + deleteCache(middlewareManifestPath) + await writeFileAtomic( + middlewareManifestPath, + JSON.stringify(middlewareManifest, null, 2) + ) +} + +async function writeActionManifest( + distDir: string, + actionManifests: ActionManifests +): Promise { + const actionManifest = await mergeActionManifests(actionManifests.values()) + const actionManifestJsonPath = join( + distDir, + 'server', + `${SERVER_REFERENCE_MANIFEST}.json` + ) + const actionManifestJsPath = join( + distDir, + 'server', + `${SERVER_REFERENCE_MANIFEST}.js` + ) + const json = JSON.stringify(actionManifest, null, 2) + deleteCache(actionManifestJsonPath) + deleteCache(actionManifestJsPath) + await writeFile(actionManifestJsonPath, json, 'utf-8') + await writeFile( + actionManifestJsPath, + `self.__RSC_SERVER_MANIFEST=${JSON.stringify(json)}`, + 'utf-8' + ) +} + +async function writeFontManifest( + distDir: string, + fontManifests: FontManifests +): Promise { + const fontManifest = mergeFontManifests(fontManifests.values()) + const json = JSON.stringify(fontManifest, null, 2) + + const fontManifestJsonPath = join( + distDir, + 'server', + `${NEXT_FONT_MANIFEST}.json` + ) + const fontManifestJsPath = join(distDir, 'server', `${NEXT_FONT_MANIFEST}.js`) + deleteCache(fontManifestJsonPath) + deleteCache(fontManifestJsPath) + await writeFileAtomic(fontManifestJsonPath, json) + await writeFileAtomic( + fontManifestJsPath, + `self.__NEXT_FONT_MANIFEST=${JSON.stringify(json)}` + ) +} + +async function writeLoadableManifest( + distDir: string, + loadableManifests: LoadableManifests +): Promise { + const loadableManifest = mergeLoadableManifests(loadableManifests.values()) + const loadableManifestPath = join(distDir, REACT_LOADABLE_MANIFEST) + const middlewareloadableManifestPath = join( + distDir, + 'server', + `${MIDDLEWARE_REACT_LOADABLE_MANIFEST}.js` + ) + + const json = JSON.stringify(loadableManifest, null, 2) + + deleteCache(loadableManifestPath) + deleteCache(middlewareloadableManifestPath) + await writeFileAtomic(loadableManifestPath, json) + await writeFileAtomic( + middlewareloadableManifestPath, + `self.__REACT_LOADABLE_MANIFEST=${JSON.stringify(json)}` + ) +} + +export async function writeManifests( + opts: SetupOpts, + distDir: string, + buildManifests: BuildManifests, + appBuildManifests: AppBuildManifests, + pagesManifests: PagesManifests, + appPathsManifests: AppPathsManifests, + middlewareManifests: MiddlewareManifests, + actionManifests: ActionManifests, + fontManifests: FontManifests, + loadableManifests: LoadableManifests, + currentEntrypoints: CurrentEntrypoints +): Promise { + await writeBuildManifest( + distDir, + buildManifests, + currentEntrypoints, + opts.fsChecker.rewrites + ) + await writeAppBuildManifest(distDir, appBuildManifests) + await writePagesManifest(distDir, pagesManifests) + await writeAppPathsManifest(distDir, appPathsManifests) + await writeMiddlewareManifest(distDir, middlewareManifests) + await writeActionManifest(distDir, actionManifests) + await writeFontManifest(distDir, fontManifests) + await writeLoadableManifest(distDir, loadableManifests) + await writeFallbackBuildManifest(distDir, buildManifests) +}