Remove missingSuspenseWithCSRBailout config (#65688)

### What

Remove `missingSuspenseWithCSRBailout` and always treate the conditions
where it was used as `true`.


### Why

This was an intended behavior introduced in 14.1, which requires users
to always add suspense boundaries if it's using any hook that could bail
out to client rendering. `missingSuspenseWithCSRBailout` as `true` was
the default behavior and you could disable it with
`missingSuspenseWithCSRBailout: false` in next config. Now after the
removal you will not be able to opt-out it.
This commit is contained in:
Jiachi Liu 2024-05-13 23:36:24 +02:00 committed by GitHub
parent e2f579e0a9
commit 99906416fc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 8 additions and 53 deletions

View file

@ -58,6 +58,8 @@ This will ensure the page does not de-opt to client-side rendering.
#### Disabling
> Note: This is only available with Next.js version 14.x. If you're in versions above 15 please fix it with the approach above.
We don't recommend disabling this rule. However, if you need to, you can disable it by setting the `missingSuspenseWithCSRBailout` option to `false` in your `next.config.js`:
```js filename="next.config.js"

View file

@ -420,8 +420,6 @@ export async function exportAppImpl(
deploymentId: nextConfig.deploymentId,
experimental: {
isAppPPREnabled: checkIsAppPPREnabled(nextConfig.experimental.ppr),
missingSuspenseWithCSRBailout:
nextConfig.experimental.missingSuspenseWithCSRBailout === true,
swrDelta: nextConfig.experimental.swrDelta,
},
}

View file

@ -169,12 +169,9 @@ export async function exportAppPage(
throw err
}
// If enabled, we should fail rendering if a client side rendering bailout
// We should fail rendering if a client side rendering bailout
// occurred at the page level.
if (
renderOpts.experimental.missingSuspenseWithCSRBailout &&
isBailoutToCSRError(err)
) {
if (isBailoutToCSRError(err)) {
throw err
}

View file

@ -1222,17 +1222,11 @@ async function renderToHTMLOrFlightImpl(
const shouldBailoutToCSR = isBailoutToCSRError(err)
if (shouldBailoutToCSR) {
const stack = getStackWithoutErrorMessage(err)
if (renderOpts.experimental.missingSuspenseWithCSRBailout) {
error(
`${err.reason} should be wrapped in a suspense boundary at page "${pagePath}". Read more: https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout\n${stack}`
)
throw err
}
warn(
`Entire page "${pagePath}" deopted into client-side rendering due to "${err.reason}". Read more: https://nextjs.org/docs/messages/deopted-into-client-rendering\n${stack}`
error(
`${err.reason} should be wrapped in a suspense boundary at page "${pagePath}". Read more: https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout\n${stack}`
)
throw err
}
if (isNotFoundError(err)) {

View file

@ -169,7 +169,6 @@ export interface RenderOptsPartial {
* prerendering.
*/
isRoutePPREnabled?: boolean
missingSuspenseWithCSRBailout: boolean
swrDelta: SwrDelta | undefined
}
postponed?: string

View file

@ -555,8 +555,6 @@ export default abstract class Server<
isExperimentalCompile: this.nextConfig.experimental.isExperimentalCompile,
experimental: {
isAppPPREnabled,
missingSuspenseWithCSRBailout:
this.nextConfig.experimental.missingSuspenseWithCSRBailout === true,
swrDelta: this.nextConfig.experimental.swrDelta,
},
}

View file

@ -417,7 +417,6 @@ export const configSchema: zod.ZodType<NextConfig> = z.lazy(() =>
staticWorkerRequestDeduping: z.boolean().optional(),
useWasmBinary: z.boolean().optional(),
useLightningcss: z.boolean().optional(),
missingSuspenseWithCSRBailout: z.boolean().optional(),
useEarlyImport: z.boolean().optional(),
testProxy: z.boolean().optional(),
defaultTestRunner: z.enum(SUPPORTED_TEST_RUNNERS_LIST).optional(),

View file

@ -418,17 +418,6 @@ export interface ExperimentalConfig {
*/
useLightningcss?: boolean
/**
* Certain methods calls like `useSearchParams()` can bail out of server-side rendering of **entire** pages to client-side rendering,
* if they are not wrapped in a suspense boundary.
*
* When this flag is set to `true`, Next.js will break the build instead of warning, to force the developer to add a suspense boundary above the method call.
*
* @note This flag will be removed in Next.js 15.
* @default true
*/
missingSuspenseWithCSRBailout?: boolean
/**
* Enables early import feature for app router modules
*/
@ -943,7 +932,6 @@ export const defaultConfig: NextConfig = {
process.env.__NEXT_EXPERIMENTAL_PPR === 'true'
),
webpackBuildWorker: undefined,
missingSuspenseWithCSRBailout: true,
optimizeServerReact: true,
useEarlyImport: false,
staleTimes: {

View file

@ -42,26 +42,6 @@ describe('missing-suspense-with-csr-bailout', () => {
await next.renameFile('app/layout.js', 'app/layout-suspense.js')
await next.renameFile('app/layout-no-suspense.js', 'app/layout.js')
})
it('should pass build if missingSuspenseWithCSRBailout os set to false', async () => {
let _content
await next.patchFile('next.config.js', (content) => {
_content = content
return content.replace(
'{}',
'{ experimental: { missingSuspenseWithCSRBailout: false } }'
)
})
const result = await next.build()
expect(result.exitCode).toBe(0)
expect(result.cliOutput).toMatch(
'⚠ Entire page "/" deopted into client-side rendering due to "useSearchParams()". Read more: https://nextjs.org/docs/messages/deopted-into-client-rendering'
)
expect(result.cliOutput).toMatch(/app\/page\.js:\d+:\d+/)
await next.patchFile('next.config.js', _content)
})
})
describe('next/dynamic', () => {