Skip to content

Commit

Permalink
fix(vercel#39609): warns about suspense and ssr
Browse files Browse the repository at this point in the history
  • Loading branch information
SukkaW committed Aug 17, 2022
1 parent 7fe5c88 commit 6ce0a1c
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 2 deletions.
15 changes: 13 additions & 2 deletions errors/invalid-dynamic-suspense.md
Expand Up @@ -2,11 +2,22 @@

#### Why This Error Occurred

`<Suspense>` is not allowed under legacy render mode when using React older than v18.
- You are using a React version older than 18 with `{ suspense: true }`.
- You are using `{ suspense: true, ssr: false }`.

#### Possible Ways to Fix It

Remove `suspense: true` option in `next/dynamic` usages.
**If you are using `{ suspense: true }` with React version older than 18**

- You can try upgrading to React 18 or newer
- If upgrading React is not an option, remove `{ suspense: true }` from `next/dynamic` usages.

**If you are using `{ suspense: true, ssr: false }`**

Next.js will use `React.lazy` when `suspense` is set to true. React 18 or newer will always try to resolve the Suspense boundary on the server. This behavior can not be disabled, thus the `ssr: false` is ignored with `suspense: true`.

- You should write code that works in both client-side and server-side.
- If rewriting the code is not an option, remove `{ suspense: true }` from `next/dynamic` usages.

### Useful Links

Expand Down
14 changes: 14 additions & 0 deletions packages/next/shared/lib/dynamic.tsx
Expand Up @@ -112,6 +112,20 @@ export default function dynamic<P = {}>(
)
}

/**
* TODO: Currently, next/dynamic will opt-in to React.lazy if { suspense: true } is used
* React 18 will always resolve the Suspense boundary on the server-side, effectively ignoring the ssr option
*
* In the future, when React Suspense with third-party libraries is stable, we can implement a custom version of
* React.lazy that can suspense on the server-side while only loading the component on the client-side
*/
if (loadableOptions.ssr === false && loadableOptions.suspense) {
loadableOptions.ssr = true
console.warn(
`"ssr: false" is ignored by next/dynamic because you can not enable "suspense" while disabling "ssr" at the same time. Read more: https://nextjs.org/docs/messages/invalid-dynamic-suspense`
)
}

// coming from build/babel/plugins/react-loadable-plugin.js
if (loadableOptions.loadableGenerated) {
loadableOptions = {
Expand Down
6 changes: 6 additions & 0 deletions test/e2e/dynamic-with-suspense/index.test.ts
Expand Up @@ -49,7 +49,13 @@ suite('dynamic with suspense', () => {

it('should render client-side', async () => {
const browser = await webdriver(next.url, '/')
const warnings = (await browser.log()).map((log) => log.message).join('\n')

expect(await hasRedbox(browser)).toBe(false)
expect(warnings).toMatch(
/"ssr: false" is ignored by next\/dynamic because you can not enable "suspense" while disabling "ssr" at the same time/gim
)

await browser.close()
})
})

0 comments on commit 6ce0a1c

Please sign in to comment.