diff --git a/errors/missing-suspense-with-csr-bailout.mdx b/errors/missing-suspense-with-csr-bailout.mdx index bf5aa02a01324..d95cec71ba1bd 100644 --- a/errors/missing-suspense-with-csr-bailout.mdx +++ b/errors/missing-suspense-with-csr-bailout.mdx @@ -10,6 +10,8 @@ Certain methods like `useSearchParams()` opt Next.js into client-side rendering. Make sure that the method is wrapped in a suspense boundary. This way Next.js will only opt the component into client-side rendering up to the suspense boundary. +> Note: There's an option `experimental.missingSuspenseWithCSRBailout` to disable the bailout behavior while you are investigating the missing suspense boundary. But it will be removed in next major version as this is a performance de-opt. + ### Useful Links - [`useSearchParams`](https://nextjs.org/docs/app/api-reference/functions/use-search-params) diff --git a/packages/next/src/server/config-shared.ts b/packages/next/src/server/config-shared.ts index 9590b0aa1be0d..7378caefcf338 100644 --- a/packages/next/src/server/config-shared.ts +++ b/packages/next/src/server/config-shared.ts @@ -387,7 +387,8 @@ export interface ExperimentalConfig { * * 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. * - * @default false + * @note This flag will be removed in Next.js 15. + * @default true */ missingSuspenseWithCSRBailout?: boolean } @@ -866,7 +867,7 @@ export const defaultConfig: NextConfig = { ? true : false, webpackBuildWorker: undefined, - missingSuspenseWithCSRBailout: false, + missingSuspenseWithCSRBailout: true, }, } diff --git a/test/e2e/app-dir/missing-suspense-with-csr-bailout/next.config.js b/test/e2e/app-dir/missing-suspense-with-csr-bailout/next.config.js index 459c99acaf15d..3477de6e00c9f 100644 --- a/test/e2e/app-dir/missing-suspense-with-csr-bailout/next.config.js +++ b/test/e2e/app-dir/missing-suspense-with-csr-bailout/next.config.js @@ -1,8 +1,4 @@ /** @type {import("next").NextConfig} */ -const config = { - experimental: { - missingSuspenseWithCSRBailout: true, - }, -} +const config = {} module.exports = config diff --git a/test/e2e/app-dir/params-hooks-compat/app/app/[slug]/page.js b/test/e2e/app-dir/params-hooks-compat/app/app/[slug]/page.js index d8a123efbcd2b..b64e1edbf756a 100644 --- a/test/e2e/app-dir/params-hooks-compat/app/app/[slug]/page.js +++ b/test/e2e/app-dir/params-hooks-compat/app/app/[slug]/page.js @@ -1,5 +1,12 @@ 'use client' +import { Suspense } from 'react' import { ParamsComponent } from '../../../shared/params-component' -export default ParamsComponent +export default function Page() { + return ( + + + + ) +} diff --git a/test/e2e/app-dir/params-hooks-compat/shared/params-component.js b/test/e2e/app-dir/params-hooks-compat/shared/params-component.js index b3cebe7771247..3ea7943d2b89f 100644 --- a/test/e2e/app-dir/params-hooks-compat/shared/params-component.js +++ b/test/e2e/app-dir/params-hooks-compat/shared/params-component.js @@ -1,4 +1,3 @@ -import React from 'react' import { useParams, useSearchParams } from 'next/navigation' export function ParamsComponent() { diff --git a/test/e2e/app-dir/shallow-routing/app/(shallow)/pushstate-new-searchparams/page.tsx b/test/e2e/app-dir/shallow-routing/app/(shallow)/pushstate-new-searchparams/page.tsx index 4c1435c94d102..bfe28e92ff83a 100644 --- a/test/e2e/app-dir/shallow-routing/app/(shallow)/pushstate-new-searchparams/page.tsx +++ b/test/e2e/app-dir/shallow-routing/app/(shallow)/pushstate-new-searchparams/page.tsx @@ -1,7 +1,9 @@ 'use client' + +import { Suspense } from 'react' import { useSearchParams } from 'next/navigation' -export default function Page() { +function InnerPage() { const searchParams = useSearchParams() return ( <> @@ -24,3 +26,11 @@ export default function Page() { ) } + +export default function Page() { + return ( + + + + ) +} diff --git a/test/e2e/app-dir/shallow-routing/app/(shallow)/pushstate-string-url/page.tsx b/test/e2e/app-dir/shallow-routing/app/(shallow)/pushstate-string-url/page.tsx index 20f9f07f324d0..2eacff1bf9347 100644 --- a/test/e2e/app-dir/shallow-routing/app/(shallow)/pushstate-string-url/page.tsx +++ b/test/e2e/app-dir/shallow-routing/app/(shallow)/pushstate-string-url/page.tsx @@ -1,7 +1,9 @@ 'use client' + +import { Suspense } from 'react' import { useSearchParams } from 'next/navigation' -export default function Page() { +function InnerPage() { const searchParams = useSearchParams() return ( <> @@ -57,3 +59,11 @@ export default function Page() { ) } + +export default function Page() { + return ( + + + + ) +} diff --git a/test/e2e/app-dir/shallow-routing/app/(shallow)/replacestate-new-searchparams/page.tsx b/test/e2e/app-dir/shallow-routing/app/(shallow)/replacestate-new-searchparams/page.tsx index fe92608bc8a09..68d1b4477b0cb 100644 --- a/test/e2e/app-dir/shallow-routing/app/(shallow)/replacestate-new-searchparams/page.tsx +++ b/test/e2e/app-dir/shallow-routing/app/(shallow)/replacestate-new-searchparams/page.tsx @@ -1,7 +1,9 @@ 'use client' + +import { Suspense } from 'react' import { useSearchParams } from 'next/navigation' -export default function Page() { +function InnerPage() { const searchParams = useSearchParams() return ( <> @@ -24,3 +26,11 @@ export default function Page() { ) } + +export default function Page() { + return ( + + + + ) +} diff --git a/test/e2e/app-dir/shallow-routing/app/(shallow)/replacestate-string-url/page.tsx b/test/e2e/app-dir/shallow-routing/app/(shallow)/replacestate-string-url/page.tsx index 72c9dcf715c3a..415e681959f59 100644 --- a/test/e2e/app-dir/shallow-routing/app/(shallow)/replacestate-string-url/page.tsx +++ b/test/e2e/app-dir/shallow-routing/app/(shallow)/replacestate-string-url/page.tsx @@ -1,7 +1,9 @@ 'use client' + +import { Suspense } from 'react' import { useSearchParams } from 'next/navigation' -export default function Page() { +function InnerPage() { const searchParams = useSearchParams() return ( <> @@ -57,3 +59,11 @@ export default function Page() { ) } + +export default function Page() { + return ( + + + + ) +}