Skip to content

Commit 714720f

Browse files
authored
dynamic = "error" violations should be shown in error overlay (#45893
dynamic = "error" should throw in dev mode, currently, it just gets ignored. It doesn't throw a nice custom error, but at least it isn't silently ignored anymore. Build behavior stays the same.
1 parent ddccab7 commit 714720f

File tree

4 files changed

+58
-4
lines changed

4 files changed

+58
-4
lines changed

packages/next/src/client/components/static-generation-async-storage.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export interface StaticGenerationStore {
1010
forceDynamic?: boolean
1111
revalidate?: boolean | number
1212
forceStatic?: boolean
13+
dynamicShouldError?: boolean
1314
pendingRevalidates?: Promise<any>[]
1415

1516
dynamicUsageDescription?: string

packages/next/src/client/components/static-generation-bailout.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ export function staticGenerationBailout(reason: string): boolean | never {
88
return true
99
}
1010

11+
if (staticGenerationStore?.dynamicShouldError) {
12+
throw new Error(
13+
`Page with \`dynamic = "error"\` couldn't be rendered statically because it used \`${reason}\``
14+
)
15+
}
16+
1117
if (staticGenerationStore?.isStaticGeneration) {
1218
staticGenerationStore.revalidate = 0
1319
const err = new DynamicServerError(reason)

packages/next/src/server/app-render.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,10 +1191,15 @@ export async function renderToHTMLOrFlight(
11911191
// the nested most config wins so we only force-static
11921192
// if it's configured above any parent that configured
11931193
// otherwise
1194-
if (layoutOrPageMod.dynamic === 'force-static') {
1195-
staticGenerationStore.forceStatic = true
1196-
} else if (layoutOrPageMod.dynamic !== 'error') {
1197-
staticGenerationStore.forceStatic = false
1194+
if (layoutOrPageMod.dynamic === 'error') {
1195+
staticGenerationStore.dynamicShouldError = true
1196+
} else {
1197+
staticGenerationStore.dynamicShouldError = false
1198+
if (layoutOrPageMod.dynamic === 'force-static') {
1199+
staticGenerationStore.forceStatic = true
1200+
} else {
1201+
staticGenerationStore.forceStatic = false
1202+
}
11981203
}
11991204
}
12001205

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/* eslint-env jest */
2+
import { sandbox } from './helpers'
3+
import { createNextDescribe } from 'e2e-utils'
4+
import path from 'path'
5+
6+
createNextDescribe(
7+
'dynamic = "error" in devmode',
8+
{
9+
files: path.join(__dirname, 'fixtures', 'default-template'),
10+
skipStart: true,
11+
},
12+
({ next }) => {
13+
it('should show error overlay when dynamic is forced', async () => {
14+
const { session, cleanup } = await sandbox(next, undefined, '/server')
15+
16+
// dynamic = "error" and force dynamic
17+
await session.patch(
18+
'app/server/page.js',
19+
`
20+
import { cookies } from 'next/headers';
21+
22+
import Component from '../../index'
23+
24+
export default function Page() {
25+
cookies()
26+
return <Component />
27+
}
28+
29+
export const dynamic = "error"
30+
`
31+
)
32+
33+
await session.hasRedbox(true)
34+
console.log(await session.getRedboxDescription())
35+
expect(await session.getRedboxDescription()).toMatchInlineSnapshot(
36+
`"Error: Page with \`dynamic = \\"error\\"\` couldn't be rendered statically because it used \`cookies\`"`
37+
)
38+
39+
await cleanup()
40+
})
41+
}
42+
)

0 commit comments

Comments
 (0)