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

add types for __next_app__ module loading functions #74566

Merged
merged 2 commits into from
Mar 5, 2025
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/next/src/build/templates/app-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<unknown>

// INJECT:__next_app_require__
// INJECT:__next_app_load_chunk__
Expand Down
14 changes: 8 additions & 6 deletions packages/next/src/server/app-render/action-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, (...args: unknown[]) => Promise<unknown>>
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)
Expand Down
5 changes: 3 additions & 2 deletions packages/next/src/server/app-render/app-render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<any>) => {
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') {
Expand Down
20 changes: 13 additions & 7 deletions packages/next/src/server/client-component-renderer-logger.ts
Original file line number Diff line number Diff line change
@@ -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) {
Expand All @@ -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
}
})
Comment on lines +32 to +37
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a drive-by fix mentioned in the description, the previous impl likely wasn't measuring anything because loadChunk is async

return result
},
}
}
Expand Down
Loading