Reword PPR caught bail out to avoid "postpone" terminology (#58223)

The "postpone" terminology is internal to React and can be used for more
things than just this. It's also a mechanism we may or may not rely on.

---------

Co-authored-by: Zack Tanner <zacktanner@gmail.com>
This commit is contained in:
Sebastian Markbåge 2023-11-08 17:08:24 -05:00 committed by GitHub
parent d68bbd7af7
commit 2f68e62d30
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 40 additions and 23 deletions

View file

@ -0,0 +1,27 @@
---
title: Static Bail Out Caught
---
## Why This Error Occurred
When Partial Prerendering (PPR) is enabled, using APIs that opt into Dynamic Rendering like `cookies`, `headers`, or `fetch` (such as with `cache: 'no-store'` or `revalidate: 0`) will cause React to throw a special error object to know which part of the page cannot be statically generated - while still letting the rest of it be partially static. If you catch this error, it is not safe for us to generate any static data, and your build will fail.
## Possible Ways to Fix It
- Ensure that you are not wrapping Next.js APIs that opt into dynamic rendering in a `try/catch` block.
- If you do wrap these APIs in a try/catch, make sure you re-throw the original error so it can be caught by Next.js.
- Alternatively, insert [`unstable_noStore()`](docs/app/api-reference/functions/unstable_noStore) before the try/catch.
```js
import { unstable_noStore } from 'next/cache'
async function fetchData() {
unstable_noStore() // opt out before we even get to the try/catch
try {
const response = await fetch(url);
...
} catch (x) {
...
}
}
```

View file

@ -1,13 +0,0 @@
---
title: Static Generation Postpone Error
---
## Why This Error Occurred
When Partial Prerendering (PPR) is enabled, using APIs that opt into Dynamic Rendering like `cookies`, `headers`, or `fetch` (such as with `cache: 'no-store'` or `revalidate: 0`) will cause Next.js to throw a special error to know which part of the page cannot be statically generated. If you catch this error, we will not be able to generate any static data, and your build will fail.
## Possible Ways to Fix It
- Ensure that you are not wrapping Next.js APIs that opt into dynamic rendering in a `try/catch` block.
- If you do wrap these APIs in a try/catch, make sure you re-throw the original error so it can be caught by Next.js.
- Alternatively, insert [`unstable_noStore()`](docs/app/api-reference/functions/unstable_noStore) before the try/catch.

View file

@ -22,8 +22,8 @@ export function maybePostpone(
staticGenerationStore.postponeWasTriggered = true
React.unstable_postpone(
`This page needs to opt out of static rendering at this point because it used ` +
`${reason}. React throws this special object to bail out. It should not be caught ` +
`by your own try/catch. Learn more: https://nextjs.org/docs/messages/ppr-postpone-error`
`This page needs to bail out of prerendering at this point because it used ${reason}. ` +
`React throws this special object to indicate where. It should not be caught by ` +
`your own try/catch. Learn more: https://nextjs.org/docs/messages/ppr-caught-error`
)
}

View file

@ -45,7 +45,7 @@ export const staticGenerationBailout: StaticGenerationBailout = (
link: 'https://nextjs.org/docs/messages/dynamic-server-error',
})
maybePostpone(staticGenerationStore, message)
maybePostpone(staticGenerationStore, reason)
// As this is a bailout, we don't want to revalidate, so set the revalidate
// to 0.

View file

@ -1029,7 +1029,10 @@ async function renderToHTMLOrFlightImpl(
// as we won't be able to generate the static part
warn('')
error(
`Postpone signal was caught while rendering ${urlPathname}. Check to see if you're try/catching a Next.js API such as headers / cookies, or a fetch with "no-store". Learn more: https://nextjs.org/docs/messages/ppr-postpone-error`
`Prerendering ${urlPathname} needs to partially bail out because something dynamic was used. ` +
`React throws a special object to indicate where we need to bail out but it was caught ` +
`by a try/catch or a Promise was not awaited. These special objects should not be caught ` +
`by your own try/catch. Learn more: https://nextjs.org/docs/messages/ppr-caught-error`
)
if (capturedErrors.length > 0) {

View file

@ -23,14 +23,14 @@ describe('ppr build errors', () => {
describe('when a postpone call was made but missing postpone data', () => {
it('should fail the build', async () => {
expect(stderr).toContain(
'Postpone signal was caught while rendering /. Check to see if you\'re try/catching a Next.js API such as headers / cookies, or a fetch with "no-store".'
'Prerendering / needs to partially bail out because something dynamic was used. '
)
})
it('should fail the build & surface any errors that were thrown by user code', async () => {
// in the case of catching a postpone and throwing a new error, we log the error that the user threw to help with debugging
expect(stderr).toContain(
'Postpone signal was caught while rendering /re-throwing-error. Check to see if you\'re try/catching a Next.js API such as headers / cookies, or a fetch with "no-store".'
'Prerendering /re-throwing-error needs to partially bail out because something dynamic was used. '
)
expect(stderr).toContain(
'The following error was thrown during build, and may help identify the source of the issue:'
@ -57,7 +57,7 @@ describe('ppr build errors', () => {
describe('when a postpone call was made but missing postpone data', () => {
it('should fail the build', async () => {
expect(stderr).toContain(
'Postpone signal was caught while rendering /no-suspense-boundary. Check to see if you\'re try/catching a Next.js API such as headers / cookies, or a fetch with "no-store".'
'Prerendering /no-suspense-boundary needs to partially bail out because something dynamic was used. '
)
// the regular pre-render error should not be thrown as well, as we've already logged a more specific error
@ -69,7 +69,7 @@ describe('ppr build errors', () => {
it('should fail the build & surface any errors that were thrown by user code', async () => {
// in the case of catching a postpone and throwing a new error, we log the error that the user threw to help with debugging
expect(stderr).toContain(
'Postpone signal was caught while rendering /no-suspense-boundary-re-throwing-error. Check to see if you\'re try/catching a Next.js API such as headers / cookies, or a fetch with "no-store".'
'Prerendering /no-suspense-boundary-re-throwing-error needs to partially bail out because something dynamic was used. '
)
expect(stderr).toContain(
'The following error was thrown during build, and may help identify the source of the issue:'
@ -89,7 +89,7 @@ describe('ppr build errors', () => {
describe('when a postpone call is caught and logged it should', () => {
it('should include a message telling why', async () => {
expect(stdout).toContain(
"Logged error: This page needs to opt out of static rendering at this point because it used Page couldn't be rendered statically because it used `cookies`."
"Logged error: This page needs to bail out of prerendering at this point because it used Page couldn't be rendered statically because it used `cookies`."
)
})
})