Skip to content

Commit 4984ac4

Browse files
authored
fix: Prevent duplicate file entries in modulesCode (#82550)
Fixes: #82515 When global-error, and presumably other similar files are defined by users,`next build` (Webpack) outputs this to `.next/server/app/page.js`(removed some values for brevity, see OP for more): ```js layout: [/* */], "global-error": [() => Promise.resolve().then(c.bind(c, 6076)), "/my-app/app/global-error.tsx"], "global-error": [() => Promise.resolve().then(c.bind(c, 6076)), "/my-app/app/global-error.tsx"], "not-found": [/* */], forbidden: [/* */], unauthorized: [/* */], metadata: { /* content */ } ``` Since this is then loaded into memory (copied to a JS file that's later parsed - rather), the last `global-error` key is used ( `{a: 0, a: 100}` is just `{a: 100}`) - In this case though, the duplicate keys have the same value too which makes this a **nice** to fix. This PR does a `reduceRight` pass checking if we have seen this `file` already, if so, skip. That should be safe enough to not introduce regressions. Verified Turbopack builds just for the sake of it - no "issue" there.
1 parent a5317ed commit 4984ac4

File tree

1 file changed

+8
-5
lines changed
  • packages/next/src/build/webpack/loaders/next-app-loader

1 file changed

+8
-5
lines changed

packages/next/src/build/webpack/loaders/next-app-loader/index.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ async function createTreeCodeFromPath(
287287

288288
// Fill in the loader tree for all of the special files types (layout, default, etc) at this level
289289
// `page` is not included here as it's added above.
290-
const filePaths = await Promise.all(
290+
const filePathEntries = await Promise.all(
291291
Object.values(FILE_TYPES).map(async (file) => {
292292
return [
293293
file,
@@ -302,6 +302,9 @@ async function createTreeCodeFromPath(
302302
] as const
303303
})
304304
)
305+
const filePaths = new Map<ValueOf<typeof FILE_TYPES>, string | undefined>(
306+
filePathEntries
307+
)
305308

306309
// Only resolve global-* convention files at the root layer
307310
if (isRootLayer) {
@@ -313,7 +316,7 @@ async function createTreeCodeFromPath(
313316
}
314317
// Add global-error to root layer's filePaths, so that it's always available,
315318
// by default it's the built-in global-error.js
316-
filePaths.push([GLOBAL_ERROR_FILE_TYPE, globalError])
319+
filePaths.set(GLOBAL_ERROR_FILE_TYPE, globalError)
317320

318321
// TODO(global-not-found): remove this flag assertion condition
319322
// once global-not-found is stable
@@ -326,11 +329,11 @@ async function createTreeCodeFromPath(
326329
}
327330
// Add global-not-found to root layer's filePaths, so that it's always available,
328331
// by default it's the built-in global-not-found.js
329-
filePaths.push([GLOBAL_NOT_FOUND_FILE_TYPE, globalNotFound])
332+
filePaths.set(GLOBAL_NOT_FOUND_FILE_TYPE, globalNotFound)
330333
}
331334
}
332335

333-
let definedFilePaths = filePaths.filter(
336+
let definedFilePaths = Array.from(filePaths.entries()).filter(
334337
([, filePath]) => filePath !== undefined
335338
) as [ValueOf<typeof FILE_TYPES>, string][]
336339

@@ -403,7 +406,7 @@ async function createTreeCodeFromPath(
403406
: parallelSegmentKey
404407

405408
const normalizedParallelKey = normalizeParallelKey(parallelKey)
406-
let subtreeCode
409+
let subtreeCode: string | undefined
407410
// If it's root not found page, set not-found boundary as children page
408411
if (isNotFoundRoute) {
409412
if (normalizedParallelKey === 'children') {

0 commit comments

Comments
 (0)