Skip to content

Commit 36dc5a1

Browse files
docs: update nextjs documentation (#13)
Co-authored-by: xiaoyu2er <[email protected]>
1 parent 158febe commit 36dc5a1

40 files changed

+349
-593
lines changed

apps/docs/content/en/docs/01-app/01-getting-started/01-installation.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ export default function Page() {
226226

227227
1. Run `npm run dev` to start the development server.
228228
2. Visit `http://localhost:3000` to view your application.
229-
3. Edit the<AppOnly>`app/page.tsx`</AppOnly> <PagesOnly>`pages/index.tsx`</PagesOnly> file and save it to see the updated result in your browser.
229+
3. Edit the <AppOnly>`app/page.tsx`</AppOnly><PagesOnly>`pages/index.tsx`</PagesOnly> file and save it to see the updated result in your browser.
230230

231231
## Set up TypeScript
232232

apps/docs/content/en/docs/01-app/01-getting-started/08-partial-prerendering.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ To understand Partial Prerendering, it helps to be familiar with the rendering s
3434

3535
### Static Rendering
3636

37-
With Static Rendering, HTML is generated ahead of time—either at build time or through [revalidation](/docs/app/building-your-application/data-fetching/incremental-static-regeneration). The result is cached and shared across users and requests.
37+
With Static Rendering, HTML is generated ahead of time—either at build time or through [revalidation](/docs/app/guides/incremental-static-regeneration). The result is cached and shared across users and requests.
3838

3939
In Partial Prerendering, Next.js prerenders a **static shell** for a route. This can include the layout and any other components that don't depend on request-time data.
4040

apps/docs/content/en/docs/01-app/01-getting-started/09-fetching-data.mdx

Lines changed: 272 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ related:
88
links:
99
- app/api-reference/functions/fetch
1010
- app/api-reference/file-conventions/loading
11+
- app/api-reference/config/next-config-js/logging
12+
- app/api-reference/config/next-config-js/taint
1113
---
1214

13-
This page will walk you through how you can fetch data in [Server Components](#server-components) and [Client Components](#client-components). As well as how to [stream](#streaming) content that depends on data.
15+
This page will walk you through how you can fetch data in [Server and Client Components](/docs/app/getting-started/server-and-client-components), and how to [stream](#streaming) components that depend on data.
1416

1517
## Fetching data
1618

@@ -53,6 +55,11 @@ export default async function Page() {
5355
}
5456
```
5557

58+
> **Good to know:**
59+
>
60+
> - `fetch` responses are not cached by default. However, Next.js will [prerender](/docs/app/getting-started/partial-prerendering#static-rendering) the route and the output will be cached for improved performance. If you'd like to opt into [dynamic rendering](/docs/app/getting-started/partial-prerendering#dynamic-rendering), use the `{ cache: 'no-store' }` option. See the [`fetch` API Reference](/docs/app/api-reference/functions/fetch).
61+
> - During development, you can log `fetch` calls for better visibility and debugging. See the [`logging` API reference](/docs/app/api-reference/config/next-config-js/logging).
62+
5663
#### With an ORM or database
5764

5865
Since Server Components are rendered on the server, you can safely make database queries using an ORM or database client. Turn your component into an asynchronous function, and await the call:
@@ -203,6 +210,7 @@ export default function BlogPage() {
203210

204211
```jsx filename="app/blog/page.js" switcher
205212
'use client'
213+
206214
import useSWR from 'swr'
207215

208216
const fetcher = (url) => fetch(url).then((r) => r.json())
@@ -352,3 +360,266 @@ export default function BlogPage() {
352360
An instant loading state is fallback UI that is shown immediately to the user after navigation. For the best user experience, we recommend designing loading states that are meaningful and help users understand the app is responding. For example, you can use skeletons and spinners, or a small but meaningful part of future screens such as a cover photo, title, etc.
353361

354362
In development, you can preview and inspect the loading state of your components using the [React Devtools](https://react.dev/learn/react-developer-tools).
363+
364+
## Examples
365+
366+
### Sequential data fetching
367+
368+
Sequential data fetching happens when nested components in a tree each fetch their own data and the requests are not [deduplicated](/docs/app/deep-dive/caching#request-memoization), leading to longer response times.
369+
370+
<Image
371+
alt="Sequential and Parallel Data Fetching"
372+
srcLight="/docs/light/sequential-parallel-data-fetching.png"
373+
srcDark="/docs/dark/sequential-parallel-data-fetching.png"
374+
width="1600"
375+
height="525"
376+
/>
377+
378+
There may be cases where you want this pattern because one fetch depends on the result of the other.
379+
380+
For example, the `<Playlists>` component will only start fetching data once the `<Artist>` component has finished fetching data because `<Playlists>` depends on the `artistID` prop:
381+
382+
```tsx filename="app/artist/[username]/page.tsx" switcher
383+
export default async function Page({
384+
params,
385+
}: {
386+
params: Promise<{ username: string }>
387+
}) {
388+
const { username } = await params
389+
// Get artist information
390+
const artist = await getArtist(username)
391+
392+
return (
393+
<>
394+
<h1>{artist.name}</h1>
395+
{/* Show fallback UI while the Playlists component is loading */}
396+
<Suspense fallback={<div>Loading...</div>}>
397+
{/* Pass the artist ID to the Playlists component */}
398+
<Playlists artistID={artist.id} />
399+
</Suspense>
400+
</>
401+
)
402+
}
403+
404+
async function Playlists({ artistID }: { artistID: string }) {
405+
// Use the artist ID to fetch playlists
406+
const playlists = await getArtistPlaylists(artistID)
407+
408+
return (
409+
<ul>
410+
{playlists.map((playlist) => (
411+
<li key={playlist.id}>{playlist.name}</li>
412+
))}
413+
</ul>
414+
)
415+
}
416+
```
417+
418+
```jsx filename="app/artist/[username]/page.js" switcher
419+
export default async function Page({ params }) {
420+
const { username } = await params
421+
// Get artist information
422+
const artist = await getArtist(username)
423+
424+
return (
425+
<>
426+
<h1>{artist.name}</h1>
427+
{/* Show fallback UI while the Playlists component is loading */}
428+
<Suspense fallback={<div>Loading...</div>}>
429+
{/* Pass the artist ID to the Playlists component */}
430+
<Playlists artistID={artist.id} />
431+
</Suspense>
432+
</>
433+
)
434+
}
435+
436+
async function Playlists({ artistID }) {
437+
// Use the artist ID to fetch playlists
438+
const playlists = await getArtistPlaylists(artistID)
439+
440+
return (
441+
<ul>
442+
{playlists.map((playlist) => (
443+
<li key={playlist.id}>{playlist.name}</li>
444+
))}
445+
</ul>
446+
)
447+
}
448+
```
449+
450+
To improve the user experience, you should use [React `<Suspense>`](/docs/app/building-your-application/routing/loading-ui-and-streaming#streaming-with-suspense) to show a `fallback` while data is being fetch. This will enable [streaming](#streaming) and prevent the whole route from being blocked by the sequential data requests.
451+
452+
### Parallel data fetching
453+
454+
Parallel data fetching happens when data requests in a route are eagerly initiated and start at the same time.
455+
456+
By default, [layouts and pages](/docs/app/getting-started/layouts-and-pages) are rendered in parallel. So each segment starts fetching data as soon as possible.
457+
458+
However, within _any_ component, multiple `async`/`await` requests can still be sequential if placed after the other. For example, `getAlbums` will be blocked until `getArtist` is resolved:
459+
460+
```tsx filename="app/artist/[username]/page.tsx" switcher
461+
import { getArtist, getAlbums } from '@/app/lib/data'
462+
463+
export default async function Page({ params }) {
464+
// These requests will be sequential
465+
const { username } = await params
466+
const artist = await getArtist(username)
467+
const albums = await getAlbums(username)
468+
return <div>{artist.name}</div>
469+
}
470+
```
471+
472+
You can initiate requests in parallel by defining them outside the components that use the data, and resolving them together, for example, with [`Promise.all`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all):
473+
474+
```tsx filename="app/artist/[username]/page.tsx" highlight={3,8,23} switcher
475+
import Albums from './albums'
476+
477+
async function getArtist(username: string) {
478+
const res = await fetch(`https://api.example.com/artist/${username}`)
479+
return res.json()
480+
}
481+
482+
async function getAlbums(username: string) {
483+
const res = await fetch(`https://api.example.com/artist/${username}/albums`)
484+
return res.json()
485+
}
486+
487+
export default async function Page({
488+
params,
489+
}: {
490+
params: Promise<{ username: string }>
491+
}) {
492+
const { username } = await params
493+
const artistData = getArtist(username)
494+
const albumsData = getAlbums(username)
495+
496+
// Initiate both requests in parallel
497+
const [artist, albums] = await Promise.all([artistData, albumsData])
498+
499+
return (
500+
<>
501+
<h1>{artist.name}</h1>
502+
<Albums list={albums} />
503+
</>
504+
)
505+
}
506+
```
507+
508+
```jsx filename="app/artist/[username]/page.js" highlight={3,8,19} switcher
509+
import Albums from './albums'
510+
511+
async function getArtist(username) {
512+
const res = await fetch(`https://api.example.com/artist/${username}`)
513+
return res.json()
514+
}
515+
516+
async function getAlbums(username) {
517+
const res = await fetch(`https://api.example.com/artist/${username}/albums`)
518+
return res.json()
519+
}
520+
521+
export default async function Page({ params }) {
522+
const { username } = await params
523+
const artistData = getArtist(username)
524+
const albumsData = getAlbums(username)
525+
526+
// Initiate both requests in parallel
527+
const [artist, albums] = await Promise.all([artistData, albumsData])
528+
529+
return (
530+
<>
531+
<h1>{artist.name}</h1>
532+
<Albums list={albums} />
533+
</>
534+
)
535+
}
536+
```
537+
538+
> **Good to know:** If one request fails when using `Promise.all`, the entire operation will fail. To handle this, you can use the [`Promise.allSettled`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled) method instead.
539+
540+
### Preloading data
541+
542+
You can preload data by creating an utility function that you eagerly call above blocking requests. `<Item>` conditionally renders based on the `checkIsAvailable()` function.
543+
544+
You can call `preload()` before `checkIsAvailable()` to eagerly initiate `<Item/>` data dependencies. By the time `<Item/>` is rendered, its data has already been fetched.
545+
546+
```tsx filename="app/item/[id]/page.tsx" switcher
547+
import { getItem } from '@/lib/data'
548+
549+
export default async function Page({
550+
params,
551+
}: {
552+
params: Promise<{ id: string }>
553+
}) {
554+
const { id } = await params
555+
// starting loading item data
556+
preload(id)
557+
// perform another asynchronous task
558+
const isAvailable = await checkIsAvailable()
559+
560+
return isAvailable ? <Item id={id} /> : null
561+
}
562+
563+
export const preload = (id: string) => {
564+
// void evaluates the given expression and returns undefined
565+
// https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/void
566+
void getItem(id)
567+
}
568+
export async function Item({ id }: { id: string }) {
569+
const result = await getItem(id)
570+
// ...
571+
}
572+
```
573+
574+
```jsx filename="app/item/[id]/page.js" switcher
575+
import { getItem } from '@/lib/data'
576+
577+
export default async function Page({ params }) {
578+
const { id } = await params
579+
// starting loading item data
580+
preload(id)
581+
// perform another asynchronous task
582+
const isAvailable = await checkIsAvailable()
583+
584+
return isAvailable ? <Item id={id} /> : null
585+
}
586+
587+
export const preload = (id) => {
588+
// void evaluates the given expression and returns undefined
589+
// https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/void
590+
void getItem(id)
591+
}
592+
export async function Item({ id }) {
593+
const result = await getItem(id)
594+
// ...
595+
```
596+
597+
Additionally, you can use React's [`cache` function](https://react.dev/reference/react/cache) and the [`server-only` package](https://www.npmjs.com/package/server-only) to create a reusable utility function. This approach allows you to cache the data fetching function and ensure that it's only executed on the server.
598+
599+
```ts filename="utils/get-item.ts" switcher
600+
import { cache } from 'react'
601+
import 'server-only'
602+
import { getItem } from '@/lib/data'
603+
604+
export const preload = (id: string) => {
605+
void getItem(id)
606+
}
607+
608+
export const getItem = cache(async (id: string) => {
609+
// ...
610+
})
611+
```
612+
613+
```js filename="utils/get-item.js" switcher
614+
import { cache } from 'react'
615+
import 'server-only'
616+
import { getItem } from '@/lib/data'
617+
618+
export const preload = (id) => {
619+
void getItem(id)
620+
}
621+
622+
export const getItem = cache(async (id) => {
623+
// ...
624+
})
625+
```

apps/docs/content/en/docs/01-app/01-getting-started/11-error-handling.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ Errors will bubble up to the nearest parent error boundary. This allows for gran
274274
275275
### Global errors
276276
277-
While less common, you can handle errors in the root layout using the [`global-error.js`](/docs/app/api-reference/file-conventions/error#global-error) file, located in the root app directory, even when leveraging [internationalization](/docs/app/building-your-application/routing/internationalization). Global error UI must define its own `<html>` and `<body>` tags, since it is replacing the root layout or template when active.
277+
While less common, you can handle errors in the root layout using the [`global-error.js`](/docs/app/api-reference/file-conventions/error#global-error) file, located in the root app directory, even when leveraging [internationalization](/docs/app/guides/internationalization). Global error UI must define its own `<html>` and `<body>` tags, since it is replacing the root layout or template when active.
278278
279279
```tsx filename="app/global-error.tsx" switcher
280280
'use client' // Error boundaries must be Client Components
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
2-
title: Incremental Static Regeneration (ISR)
2+
title: How to implement Incremental Static Regeneration (ISR)
3+
nav_title: ISR
34
description: Learn how to create or update static pages at runtime with Incremental Static Regeneration.
45
---
56

apps/docs/content/en/docs/01-app/02-guides/index.mdx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ description: Learn how to implement common UI patterns and use cases using Next.
55

66
### Data Fetching
77

8-
- [Using the `fetch` API](/docs/app/building-your-application/data-fetching/fetching#fetching-data-on-the-server-with-the-fetch-api)
9-
- [Using an ORM or database client](/docs/app/building-your-application/data-fetching/fetching#fetching-data-on-the-server-with-an-orm-or-database)
8+
- [Using the `fetch` API](/docs/app/getting-started/fetching-data#with-the-fetch-api)
9+
- [Using an ORM or database client](/docs/app/getting-started/fetching-data#with-an-orm-or-database)
1010
- [Reading search params on the server](/docs/app/api-reference/file-conventions/page)
1111
- [Reading search params on the client](/docs/app/api-reference/functions/use-search-params)
1212

1313
### Revalidating Data
1414

15-
- [Using ISR to revalidate data after a certain time](/docs/app/building-your-application/data-fetching/incremental-static-regeneration#time-based-revalidation)
16-
- [Using ISR to revalidate data on-demand](/docs/app/building-your-application/data-fetching/incremental-static-regeneration#on-demand-revalidation-with-revalidatepath)
15+
- [Using ISR to revalidate data after a certain time](/docs/app/guides/incremental-static-regeneration#time-based-revalidation)
16+
- [Using ISR to revalidate data on-demand](/docs/app/guides/incremental-static-regeneration#on-demand-revalidation-with-revalidatepath)
1717

1818
### Forms
1919

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ export default async function Page({ params }) {
168168

169169
Because all layouts and pages in the `app/` directory default to [Server Components](/docs/app/getting-started/server-and-client-components), we do not need to worry about the size of the translation files affecting our client-side JavaScript bundle size. This code will **only run on the server**, and only the resulting HTML will be sent to the browser.
170170

171-
## Static Generation
171+
## Static Rendering
172172

173173
To generate static routes for a given set of locales, we can use `generateStaticParams` with any page or layout. This can be global, for example, in the root layout:
174174

apps/docs/content/en/docs/01-app/02-guides/migrating/app-router-migration.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ export default function ExampleClientComponent() {
470470
In addition, the new `useRouter` hook has the following changes:
471471

472472
- `isFallback` has been removed because `fallback` has [been replaced](#replacing-fallback).
473-
- The `locale`, `locales`, `defaultLocales`, `domainLocales` values have been removed because built-in i18n Next.js features are no longer necessary in the `app` directory. [Learn more about i18n](/docs/app/building-your-application/routing/internationalization).
473+
- The `locale`, `locales`, `defaultLocales`, `domainLocales` values have been removed because built-in i18n Next.js features are no longer necessary in the `app` directory. [Learn more about i18n](/docs/app/guides/internationalization).
474474
- `basePath` has been removed. The alternative will not be part of `useRouter`. It has not yet been implemented.
475475
- `asPath` has been removed because the concept of `as` has been removed from the new router.
476476
- `isReady` has been removed because it is no longer necessary. During [static rendering](/docs/app/getting-started/partial-prerendering#static-rendering), any component that uses the [`useSearchParams()`](/docs/app/api-reference/functions/use-search-params) hook will skip the prerendering step and instead be rendered on the client at runtime.

apps/docs/content/en/docs/01-app/02-guides/migrating/from-create-react-app.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Depending on your needs, Next.js allows you to choose your data fetching strateg
3939

4040
### Middleware
4141

42-
[Next.js Middleware](/docs/app/building-your-application/routing/middleware) allows you to run code on the server before a request is completed. For instance, you can avoid a flash of unauthenticated content by redirecting a user to a login page in the middleware for authenticated-only pages. You can also use it for features like A/B testing, experimentation, and [internationalization](/docs/app/building-your-application/routing/internationalization).
42+
[Next.js Middleware](/docs/app/building-your-application/routing/middleware) allows you to run code on the server before a request is completed. For instance, you can avoid a flash of unauthenticated content by redirecting a user to a login page in the middleware for authenticated-only pages. You can also use it for features like A/B testing, experimentation, and [internationalization](/docs/app/guides/internationalization).
4343

4444
### Built-in Optimizations
4545

apps/docs/content/en/docs/01-app/02-guides/migrating/from-vite.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Depending on your needs, Next.js allows you to choose your data fetching strateg
3939

4040
### Middleware
4141

42-
[Next.js Middleware](/docs/app/building-your-application/routing/middleware) allows you to run code on the server before a request is completed. This is especially useful to avoid having a flash of unauthenticated content when the user visits an authenticated-only page by redirecting the user to a login page. The middleware is also useful for experimentation and [internationalization](/docs/app/building-your-application/routing/internationalization).
42+
[Next.js Middleware](/docs/app/building-your-application/routing/middleware) allows you to run code on the server before a request is completed. This is especially useful to avoid having a flash of unauthenticated content when the user visits an authenticated-only page by redirecting the user to a login page. The middleware is also useful for experimentation and [internationalization](/docs/app/guides/internationalization).
4343

4444
### Built-in Optimizations
4545

0 commit comments

Comments
 (0)