Skip to content

Commit 2478adb

Browse files
huozhipull[bot]
authored andcommitted
dx: add pagePath info to missing component error (#66916)
### What Show the full `pagePath` information for missing default component app router convention files. Move runtime error tests from `rsc-build-errors.test.ts` to the new test `test/development/acceptance-app/undefined-default-export.test.ts` ### Why Previously we only log `segment` which could be `[slug]` that is not enough useful for users to locate the bad defined component
1 parent 51ec3f6 commit 2478adb

File tree

3 files changed

+100
-47
lines changed

3 files changed

+100
-47
lines changed

packages/next/src/server/app-render/create-component-tree.tsx

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ export function createComponentTree(props: {
5151
)
5252
}
5353

54+
function errorMissingDefaultExport(pagePath: string, convention: string) {
55+
throw new Error(
56+
`The default export is not a React Component in "${pagePath}/${convention}"`
57+
)
58+
}
59+
5460
async function createComponentTreeInternal({
5561
createSegmentPath,
5662
loaderTree: tree,
@@ -311,30 +317,22 @@ async function createComponentTreeInternal({
311317
(isPage || typeof Component !== 'undefined') &&
312318
!isValidElementType(Component)
313319
) {
314-
throw new Error(
315-
`The default export is not a React Component in page: "${pagePath}"`
316-
)
320+
errorMissingDefaultExport(pagePath, 'page')
317321
}
318322

319323
if (
320324
typeof ErrorComponent !== 'undefined' &&
321325
!isValidElementType(ErrorComponent)
322326
) {
323-
throw new Error(
324-
`The default export of error is not a React Component in page: ${segment}`
325-
)
327+
errorMissingDefaultExport(pagePath, 'error')
326328
}
327329

328330
if (typeof Loading !== 'undefined' && !isValidElementType(Loading)) {
329-
throw new Error(
330-
`The default export of loading is not a React Component in ${segment}`
331-
)
331+
errorMissingDefaultExport(pagePath, 'loading')
332332
}
333333

334334
if (typeof NotFound !== 'undefined' && !isValidElementType(NotFound)) {
335-
throw new Error(
336-
`The default export of notFound is not a React Component in ${segment}`
337-
)
335+
errorMissingDefaultExport(pagePath, 'not-found')
338336
}
339337
}
340338

test/development/acceptance-app/rsc-build-errors.test.ts

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -124,41 +124,6 @@ describe('Error overlay - RSC build errors', () => {
124124
await cleanup()
125125
})
126126

127-
it('should error when page component export is not valid', async () => {
128-
const { session, cleanup } = await sandbox(
129-
next,
130-
undefined,
131-
'/server-with-errors/page-export'
132-
)
133-
134-
await next.patchFile(
135-
'app/server-with-errors/page-export/page.js',
136-
'export const a = 123'
137-
)
138-
139-
await session.assertHasRedbox()
140-
expect(await session.getRedboxDescription()).toInclude(
141-
'The default export is not a React Component in page: "/server-with-errors/page-export"'
142-
)
143-
144-
await cleanup()
145-
})
146-
147-
it('should error when page component export is not valid on initial load', async () => {
148-
const { session, cleanup } = await sandbox(
149-
next,
150-
undefined,
151-
'/server-with-errors/page-export-initial-error'
152-
)
153-
154-
await session.assertHasRedbox()
155-
expect(await session.getRedboxDescription()).toInclude(
156-
'The default export is not a React Component in page: "/server-with-errors/page-export-initial-error"'
157-
)
158-
159-
await cleanup()
160-
})
161-
162127
it('should throw an error when "use client" is on the top level but after other expressions', async () => {
163128
const { session, cleanup } = await sandbox(
164129
next,
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import path from 'path'
2+
import { FileRef, nextTestSetup } from 'e2e-utils'
3+
import { sandbox } from 'development-sandbox'
4+
5+
describe('Undefined default export', () => {
6+
const { next } = nextTestSetup({
7+
files: new FileRef(path.join(__dirname, 'fixtures', 'default-template')),
8+
})
9+
10+
it('should error if page component does not have default export', async () => {
11+
const { session, cleanup } = await sandbox(
12+
next,
13+
new Map([
14+
['app/(group)/specific-path/server/page.js', 'export const a = 123'],
15+
]),
16+
'/specific-path/server'
17+
)
18+
19+
await session.assertHasRedbox()
20+
expect(await session.getRedboxDescription()).toInclude(
21+
'The default export is not a React Component in "/specific-path/server/page"'
22+
)
23+
24+
await cleanup()
25+
})
26+
27+
it('should error if not-found component does not have default export when trigger not-found boundary', async () => {
28+
const { session, cleanup } = await sandbox(
29+
next,
30+
new Map([
31+
[
32+
'app/will-not-found/page.js',
33+
`
34+
import { notFound } from 'next/navigation'
35+
export default function Page() { notFound() }
36+
`,
37+
],
38+
['app/will-not-found/not-found.js', 'export const a = 123'],
39+
]),
40+
'/will-not-found'
41+
)
42+
43+
await session.assertHasRedbox()
44+
expect(await session.getRedboxDescription()).toInclude(
45+
'The default export is not a React Component in "/will-not-found/not-found"'
46+
)
47+
48+
await cleanup()
49+
})
50+
51+
it('should error when page component export is not valid', async () => {
52+
const { session, cleanup } = await sandbox(
53+
next,
54+
undefined,
55+
'/server-with-errors/page-export'
56+
)
57+
58+
await next.patchFile(
59+
'app/server-with-errors/page-export/page.js',
60+
'export const a = 123'
61+
)
62+
63+
await session.assertHasRedbox()
64+
expect(await session.getRedboxDescription()).toInclude(
65+
'The default export is not a React Component in "/server-with-errors/page-export/page"'
66+
)
67+
68+
await cleanup()
69+
})
70+
71+
it('should error when page component export is not valid on initial load', async () => {
72+
const { session, cleanup } = await sandbox(
73+
next,
74+
new Map([
75+
[
76+
'app/server-with-errors/page-export-initial-error/page.js',
77+
'export const a = 123',
78+
],
79+
]),
80+
'/server-with-errors/page-export-initial-error'
81+
)
82+
83+
await session.assertHasRedbox()
84+
expect(await session.getRedboxDescription()).toInclude(
85+
'The default export is not a React Component in "/server-with-errors/page-export-initial-error/page"'
86+
)
87+
88+
await cleanup()
89+
})
90+
})

0 commit comments

Comments
 (0)