diff --git a/packages/next/src/build/templates/app-page.ts b/packages/next/src/build/templates/app-page.ts index 279d4dca26167..87cf0c811f76c 100644 --- a/packages/next/src/build/templates/app-page.ts +++ b/packages/next/src/build/templates/app-page.ts @@ -21,8 +21,8 @@ export { tree, pages } export { default as GlobalError } from 'VAR_MODULE_GLOBAL_ERROR' with { 'turbopack-transition': 'next-server-utility' } // These are injected by the loader afterwards. -declare const __next_app_require__: any -declare const __next_app_load_chunk__: any +declare const __next_app_require__: (id: string | number) => unknown +declare const __next_app_load_chunk__: (id: string | number) => Promise // INJECT:__next_app_require__ // INJECT:__next_app_load_chunk__ diff --git a/packages/next/src/server/app-render/action-handler.ts b/packages/next/src/server/app-render/action-handler.ts index e08d15399c05c..ac763262807ad 100644 --- a/packages/next/src/server/app-render/action-handler.ts +++ b/packages/next/src/server/app-render/action-handler.ts @@ -912,12 +912,14 @@ export async function handleAction({ } } - const actionHandler = ( - await ComponentMod.__next_app__.require(actionModId) - )[ - // `actionId` must exist if we got here, as otherwise we would have thrown an error above - actionId! - ] + const actionMod = (await ComponentMod.__next_app__.require( + actionModId + )) as Record Promise> + const actionHandler = + actionMod[ + // `actionId` must exist if we got here, as otherwise we would have thrown an error above + actionId! + ] const returnVal = await workUnitAsyncStorage.run(requestStore, () => actionHandler.apply(null, boundActionArguments) diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx index 80d0fb22ceb3f..0510318d83b0b 100644 --- a/packages/next/src/server/app-render/app-render.tsx +++ b/packages/next/src/server/app-render/app-render.tsx @@ -1189,12 +1189,13 @@ async function renderToHTMLOrFlightImpl( // cache reads we wrap the loadChunk in this tracking. This allows us // to treat chunk loading with similar semantics as cache reads to avoid // async loading chunks from causing a prerender to abort too early. - // @ts-ignore - globalThis.__next_chunk_load__ = (...args: Array) => { + const __next_chunk_load__: typeof instrumented.loadChunk = (...args) => { const loadingChunk = instrumented.loadChunk(...args) trackChunkLoading(loadingChunk) return loadingChunk } + // @ts-expect-error + globalThis.__next_chunk_load__ = __next_chunk_load__ } if (process.env.NODE_ENV === 'development') { diff --git a/packages/next/src/server/client-component-renderer-logger.ts b/packages/next/src/server/client-component-renderer-logger.ts index 7364961371de7..20b5febca26ca 100644 --- a/packages/next/src/server/client-component-renderer-logger.ts +++ b/packages/next/src/server/client-component-renderer-logger.ts @@ -1,15 +1,19 @@ +import type { AppPageModule } from './route-modules/app-page/module' + // Combined load times for loading client components let clientComponentLoadStart = 0 let clientComponentLoadTimes = 0 let clientComponentLoadCount = 0 -export function wrapClientComponentLoader(ComponentMod: any) { +export function wrapClientComponentLoader( + ComponentMod: AppPageModule +): AppPageModule['__next_app__'] { if (!('performance' in globalThis)) { return ComponentMod.__next_app__ } return { - require: (...args: any[]) => { + require: (...args) => { const startTime = performance.now() if (clientComponentLoadStart === 0) { @@ -23,13 +27,15 @@ export function wrapClientComponentLoader(ComponentMod: any) { clientComponentLoadTimes += performance.now() - startTime } }, - loadChunk: (...args: any[]) => { + loadChunk: (...args) => { const startTime = performance.now() - try { - return ComponentMod.__next_app__.loadChunk(...args) - } finally { + const result = ComponentMod.__next_app__.loadChunk(...args) + // Avoid wrapping `loadChunk`'s result in an extra promise in case something like React depends on its identity. + // We only need to know when it's settled. + result.finally(() => { clientComponentLoadTimes += performance.now() - startTime - } + }) + return result }, } }