Skip to content

Commit bdd41bb

Browse files
Docs: Updating guides on PPR and ISR (#81307)
The PR fixes issues in two different guides. ### PPR In PPR, the code for jsx and tsx versions should use the language switcher. Currently, these are displayed below each other in the guide which seems unintentional. ### ISR This change fixes multiple issues: **fixes in the example:** the example currently does not match the text below (_Here's how this example works:_). It says: > If /blog/26 is requested, Next.js will generate and cache this page on-demand that is of course not correct because there are only 25 blog posts returned from the API. No blog post data is returned for `/blog/26`, making this example wrong and confusing. By slicing the posts and supplying only 24 of 25 blog posts for static generation during the build process, the guide becomes much more explicit - the 25th blog post can be used for inspecting the workings of the on-the-fly generation and caching. Turning `dynamicParams` to `false` or `true`, one can now truly test this behaviour with the 25th blog. Second, the same example in Pages Router docs includes: > return { paths, fallback: false } In this case, again, this part below: > If /blog/26 is requested, Next.js will generate and cache this page on-demand is incorrect. When setting `fallback` to `false`, the page is never generated on-demand and returns 404 instead as there is no 26th blog post in the fetched data. So the fix changes the value of `fallback` to `blocking`, to mirror the App Router's `dynamicParams` value in the guide. This makes is more consistent and, more importantly, reproducible example. **clarifying the on-demand section:** The sections dedicated to **on-demand revalidation** do not currently mention that revalidation works differently from the time-based one. One may assume the first request after on-demand revalidation returns stale data (just like time-based). But that's not true, the next request after on-demand revalidation (with Server Actions for example) generates the content on-the-fly and returns fresh data right away. It wasn't clear to me so I tested it myself and was surprised (and happy) that it is this smart. I think it's very important to clarify this distinction in the guide. ----- I hope this makes sense. I'm quite responsive these days and will change it based on your feedback (if any). Thanks! <!-- Thanks for opening a PR! Your contribution is much appreciated. To make sure your PR is handled as smoothly as possible we request that you follow the checklist sections below. Choose the right checklist for the change(s) that you're making: ## For Contributors ### Improving Documentation - Run `pnpm prettier-fix` to fix formatting issues before opening the PR. - Read the Docs Contribution Guide to ensure your contribution follows the docs guidelines: https://nextjs.org/docs/community/contribution-guide ### Adding or Updating Examples - The "examples guidelines" are followed from our contributing doc https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md - Make sure the linting passes by running `pnpm build && pnpm lint`. See https://github.com/vercel/next.js/blob/canary/contributing/repository/linting.md ### Fixing a bug - Related issues linked using `fixes #number` - Tests added. See: https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs - Errors have a helpful link attached, see https://github.com/vercel/next.js/blob/canary/contributing.md ### Adding a feature - Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. (A discussion must be opened, see https://github.com/vercel/next.js/discussions/new?category=ideas) - Related issues/discussions are linked using `fixes #number` - e2e tests added (https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) - Documentation added - Telemetry added. In case of a feature if it's used or not. - Errors have a helpful link attached, see https://github.com/vercel/next.js/blob/canary/contributing.md ## For Maintainers - Minimal description (aim for explaining to someone not on the team to understand the PR) - When linking to a Slack thread, you might want to share details of the conclusion - Link both the Linear (Fixes NEXT-xxx) and the GitHub issues - Add review comments if necessary to explain to the reviewer the logic behind a change ### What? ### Why? ### How? Closes NEXT- Fixes # --> --------- Co-authored-by: Joseph <joseph.chamochumbi@vercel.com>
1 parent 2da86a4 commit bdd41bb

File tree

2 files changed

+21
-27
lines changed

2 files changed

+21
-27
lines changed

docs/01-app/01-getting-started/06-partial-prerendering.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ export default function Layout({ children }: { children: React.ReactNode }) {
142142
}
143143
```
144144

145-
```jsx filename="/app/dashboard/layout.js" switcher
145+
```jsx filename="/app/dashboard/layout.jsx" switcher
146146
export const experimental_ppr = true
147147

148148
export default function Layout({ children }) {

docs/01-app/02-guides/incremental-static-regeneration.mdx

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,6 @@ interface Post {
3535
// request comes in, at most once every 60 seconds.
3636
export const revalidate = 60
3737

38-
// We'll prerender only the params from `generateStaticParams` at build time.
39-
// If a request comes in for a path that hasn't been generated,
40-
// Next.js will server-render the page on-demand.
41-
export const dynamicParams = true // or false, to 404 on unknown paths
42-
4338
export async function generateStaticParams() {
4439
const posts: Post[] = await fetch('https://api.vercel.app/blog').then((res) =>
4540
res.json()
@@ -67,16 +62,11 @@ export default async function Page({
6762
}
6863
```
6964

70-
```jsx filename="app/blog/[id]/page.js" switcher
65+
```jsx filename="app/blog/[id]/page.jsx" switcher
7166
// Next.js will invalidate the cache when a
7267
// request comes in, at most once every 60 seconds.
7368
export const revalidate = 60
7469

75-
// We'll prerender only the params from `generateStaticParams` at build time.
76-
// If a request comes in for a path that hasn't been generated,
77-
// Next.js will server-render the page on-demand.
78-
export const dynamicParams = true // or false, to 404 on unknown paths
79-
8070
export async function generateStaticParams() {
8171
const posts = await fetch('https://api.vercel.app/blog').then((res) =>
8272
res.json()
@@ -100,6 +90,15 @@ export default async function Page({ params }) {
10090
}
10191
```
10292

93+
Here's how this example works:
94+
95+
1. During `next build`, all known blog posts are generated
96+
2. All requests made to these pages (e.g. `/blog/1`) are cached and instantaneous
97+
3. After 60 seconds has passed, the next request will still return the cached (now stale) page
98+
4. The cache is invalidated and a new version of the page begins generating in the background
99+
5. Once generated successfully, the next request will return the updated page and cache it for subsequent requests
100+
6. If `/blog/26` is requested, and it exists, the page will be generated on-demand. This behavior can be changed by using a different [dynamicParams](https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamicparams) value. However, if the post does not exist, then 404 is returned.
101+
103102
</AppOnly>
104103

105104
<PagesOnly>
@@ -125,10 +124,7 @@ export const getStaticPaths: GetStaticPaths = async () => {
125124
params: { id: String(post.id) },
126125
}))
127126

128-
// We'll prerender only these paths at build time.
129-
// { fallback: 'blocking' } will server-render pages
130-
// on-demand if the path doesn't exist.
131-
return { paths, fallback: false }
127+
return { paths, fallback: 'blocking' }
132128
}
133129

134130
export const getStaticProps: GetStaticProps<Props> = async ({
@@ -167,9 +163,7 @@ export async function getStaticPaths() {
167163
params: { id: post.id },
168164
}))
169165

170-
// We'll prerender only these paths at build time.
171-
// { fallback: false } means other routes should 404.
172-
return { paths, fallback: false }
166+
return { paths, fallback: 'blocking' }
173167
}
174168

175169
export async function getStaticProps({ params }) {
@@ -195,16 +189,16 @@ export default function Page({ post }) {
195189
}
196190
```
197191

198-
</PagesOnly>
199-
200192
Here's how this example works:
201193

202-
1. During `next build`, all known blog posts are generated (there are 25 in this example)
194+
1. During `next build`, all known blog posts are generated
203195
2. All requests made to these pages (e.g. `/blog/1`) are cached and instantaneous
204-
3. After 60 seconds has passed, the next request will still show the cached (stale) page
196+
3. After 60 seconds has passed, the next request will still return the cached (now stale) page
205197
4. The cache is invalidated and a new version of the page begins generating in the background
206-
5. Once generated successfully, Next.js will display and cache the updated page
207-
6. If `/blog/26` is requested, Next.js will generate and cache this page on-demand
198+
5. Once generated successfully, the next request will return the updated page and cache it for subsequent requests
199+
6. If `/blog/26` is requested, and it exists, the page will be generated on-demand. This behavior can be changed by using a different [fallback](https://nextjs.org/docs/pages/api-reference/functions/get-static-paths#fallback-false) value. However, if the post does not exist, then 404 is returned.
200+
201+
</PagesOnly>
208202

209203
## Reference
210204

@@ -237,7 +231,7 @@ Here's how this example works:
237231

238232
### Time-based revalidation
239233

240-
This fetches and displays a list of blog posts on `/blog`. After an hour, the cache for this page is invalidated on the next visit to the page. Then, in the background, a new version of the page is generated with the latest blog posts.
234+
This fetches and displays a list of blog posts on /blog. After an hour has passed, the next visitor will still receive the cached (stale) version of the page immediately for a fast response. Simultaneously, Next.js triggers regeneration of a fresh version in the background. Once the new version is successfully generated, it replaces the cached version, and subsequent visitors will receive the updated content.
241235

242236
```tsx filename="app/blog/page.tsx" switcher
243237
interface Post {
@@ -289,7 +283,7 @@ We recommend setting a high revalidation time. For instance, 1 hour instead of 1
289283

290284
For a more precise method of revalidation, invalidate pages on-demand with the `revalidatePath` function.
291285

292-
For example, this Server Action would get called after adding a new post. Regardless of how you retrieve your data in your Server Component, either using `fetch` or connecting to a database, this will clear the cache for the entire route and allow the Server Component to fetch fresh data.
286+
For example, this Server Action would get called after adding a new post. Regardless of how you retrieve your data in your Server Component, either using `fetch` or connecting to a database, this will immediately clear the cache for the entire route. Unlike time-based revalidation, the next request after on-demand revalidation won't return stale data but will serve the updated version right away and cache it for subsequent requests.
293287

294288
```ts filename="app/actions.ts" switcher
295289
'use server'

0 commit comments

Comments
 (0)