Skip to content

Commit

Permalink
docs: Next.js 14 (#57342)
Browse files Browse the repository at this point in the history
- Fetch logging configuration is no longer experimental
- Add `unstable_noStore` reference
- Add `unstable_cache` reference
- Add codemod docs for `next/og` import changes
- Update docs around stable Server Actions
- Add example of revalidating the entire data cache
- Update static export docs for `next export` command removal
- Update minimum required Node.js version
- Add `viewport` and `generateViewport` reference

Co-authored-by: Balázs Orbán <18369201+balazsorban44@users.noreply.github.com>
Co-authored-by: Delba de Oliveira <32464864+delbaoliveira@users.noreply.github.com>
  • Loading branch information
3 people authored Oct 26, 2023
1 parent fd0a96f commit 92b4d67
Show file tree
Hide file tree
Showing 27 changed files with 459 additions and 203 deletions.
2 changes: 1 addition & 1 deletion docs/01-getting-started/01-installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ related:

System Requirements:

- [Node.js 16.14](https://nodejs.org/) or later.
- [Node.js 18.17](https://nodejs.org/) or later.
- macOS, Windows (including WSL), and Linux are supported.

## Automatic Installation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ There are four ways you can fetch data:

Next.js extends the native [`fetch` Web API](https://developer.mozilla.org/docs/Web/API/Fetch_API) to allow you to configure the [caching](#caching-data) and [revalidating](#revalidating-data) behavior for each fetch request on the server. React extends `fetch` to automatically [memoize](/docs/app/building-your-application/data-fetching/patterns#fetching-data-where-its-needed) fetch requests while rendering a React component tree.

You can use `fetch` with [`async`/`await` in Server Components](https://github.com/acdlite/rfcs/blob/first-class-promises/text/0000-first-class-support-for-promises.md), in [Route Handlers](/docs/app/building-your-application/routing/route-handlers), and in [Server Actions](/docs/app/building-your-application/data-fetching/forms-and-mutations).
You can use `fetch` with `async`/`await` in Server Components, in [Route Handlers](/docs/app/building-your-application/routing/route-handlers), and in [Server Actions](/docs/app/building-your-application/data-fetching/forms-and-mutations).

For example:

Expand Down Expand Up @@ -117,7 +117,7 @@ Learn more about [time-based revalidation](/docs/app/building-your-application/c

#### On-demand Revalidation

Data can be revalidated on-demand by path ([`revalidatePath`](/docs/app/api-reference/functions/revalidatePath)) or by cache tag ([`revalidateTag`](/docs/app/api-reference/functions/revalidateTag)) inside a Route Handler or a Server Action.
Data can be revalidated on-demand by path ([`revalidatePath`](/docs/app/api-reference/functions/revalidatePath)) or by cache tag ([`revalidateTag`](/docs/app/api-reference/functions/revalidateTag)) inside a [Server Action](/docs/app/building-your-application/data-fetching/forms-and-mutations) or [Route Handler](/docs/app/building-your-application/routing/route-handlers).

Next.js has a cache tagging system for invalidating `fetch` requests across routes.

Expand All @@ -142,89 +142,25 @@ export default async function Page() {
}
```

If using a Route Handler, you should create a secret token only known by your Next.js app. This secret will be used to prevent unauthorized revalidation attempts. For example, you can access the route (either manually or with a webhook) with the following URL structure:
You can then revalidate this `fetch` call tagged with `collection` by calling `revalidateTag` in a Server Action:

```bash filename="URL"
https://<your-site.com>/api/revalidate?tag=collection&secret=<token>
```

```ts filename="app/api/revalidate/route.ts" switcher
import { NextRequest } from 'next/server'
import { revalidateTag } from 'next/cache'

// e.g a webhook to `your-website.com/api/revalidate?tag=collection&secret=<token>`
export async function POST(request: NextRequest) {
const secret = request.nextUrl.searchParams.get('secret')
const tag = request.nextUrl.searchParams.get('tag')

if (secret !== process.env.MY_SECRET_TOKEN) {
return Response.json({ message: 'Invalid secret' }, { status: 401 })
}

if (!tag) {
return Response.json({ message: 'Missing tag param' }, { status: 400 })
}

revalidateTag(tag)
```ts filename="app/actions.ts" switcher
'use server'

return Response.json({ revalidated: true, now: Date.now() })
}
```

```js filename="app/api/revalidate/route.js" switcher
import { revalidateTag } from 'next/cache'

// e.g a webhook to `your-website.com/api/revalidate?tag=collection&secret=<token>`
export async function POST(request) {
const secret = request.nextUrl.searchParams.get('secret')
const tag = request.nextUrl.searchParams.get('tag')

if (secret !== process.env.MY_SECRET_TOKEN) {
return Response.json({ message: 'Invalid secret' }, { status: 401 })
}

if (!tag) {
return Response.json({ message: 'Missing tag param' }, { status: 400 })
}

revalidateTag(tag)

return Response.json({ revalidated: true, now: Date.now() })
export default async function action() {
revalidateTag('collection')
}
```

Alternatively, you can use [`revalidatePath`](/docs/app/api-reference/functions/revalidatePath) to revalidate all data associated with a path.
```js filename="app/actions.js" switcher
'use server'

```ts filename="app/api/revalidate/route.ts" switcher
import { NextRequest } from 'next/server'
import { revalidatePath } from 'next/cache'

export async function POST(request: NextRequest) {
const path = request.nextUrl.searchParams.get('path')

if (!path) {
return Response.json({ message: 'Missing path param' }, { status: 400 })
}

revalidatePath(path)

return Response.json({ revalidated: true, now: Date.now() })
}
```

```js filename="app/api/revalidate/route.js" switcher
import { revalidatePath } from 'next/cache'

export async function POST(request) {
const path = request.nextUrl.searchParams.get('path')

if (!path) {
return Response.json({ message: 'Missing path param' }, { status: 400 })
}

revalidatePath(path)
import { revalidateTag } from 'next/cache'

return Response.json({ revalidated: true, now: Date.now() })
export default async function action() {
revalidateTag('collection')
}
```

Expand Down Expand Up @@ -260,24 +196,15 @@ View all the available `cache` options in the [`fetch` API reference](/docs/app/

If you have multiple `fetch` requests in a route segment (e.g. a Layout or Page), you can configure the caching behavior of all data requests in the segment using the [Segment Config Options](/docs/app/api-reference/file-conventions/route-segment-config).

For example, using `const dynamic = 'force-dynamic'` will cause all data to be fetched at request time, and the segment to be rendered dynamically.

```js filename="layout.js | page.js"
// Add
export const dynamic = 'force-dynamic'
```

There's an extensive list of Segment Config options, giving you fine-grained control of static and dynamic behavior of a route segment. See the [API reference](/docs/app/api-reference/file-conventions/route-segment-config) for more.
However, we recommend configuring the caching behavior of each `fetch` request individually. This gives you more granular control over the caching behavior.

## Fetching data on the Server with third-party libraries

In cases where you're using a third-party library that doesn't support or expose `fetch` (for example, a database, CMS, or ORM client), you can configure the caching and revalidating behavior of those requests using the [Route Segment Config Option](/docs/app/api-reference/file-conventions/route-segment-config) and React's `cache` function.

Whether the data is cached or not will depend on whether the route segment is [statically or dynamically rendered](/docs/app/building-your-application/rendering/server-components#server-rendering-strategies). If the segment is static (default), the output of the request will be cached and revalidated as part of the route segment. If the segment is dynamic, the output of the request will _not_ be cached and will be re-fetched on every request when the segment is rendered.

> **Good to know:**
>
> Next.js is working on an API, `unstable_cache`, for configuring the caching and revalidating behavior of individual third-party requests.
You can also use the experimental [`unstable_cache` API](/docs/app/api-reference/functions/unstable_cache).

### Example

Expand Down Expand Up @@ -370,4 +297,4 @@ You can also fetch data on the client using a third-party library such as [SWR](

> **Future APIs**:
>
> `use` is a React function that **accepts and handles a promise** returned by a function. Wrapping `fetch` in `use` is currently **not** recommended in Client Components and may trigger multiple re-renders. Learn more about `use` in the [React RFC](https://github.com/acdlite/rfcs/blob/first-class-promises/text/0000-first-class-support-for-promises.md#usepromise).
> `use` is a React function that **accepts and handles a promise** returned by a function. Wrapping `fetch` in `use` is currently **not** recommended in Client Components and may trigger multiple re-renders. Learn more about `use` in the [React docs](https://react.dev/reference/react/use).
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ export default async function submit(formData) {

<AppOnly>

Use the `useFormStatus` hook to show a loading state when a form is submitting on the server. The `useFormStatus` hook can only be used as a child of a `form` element using a Server Action.
Use the [`useFormStatus`](https://react.dev/reference/react-dom/hooks/useFormStatus) hook to show a loading state when a form is submitting on the server. The `useFormStatus` hook can only be used as a child of a `form` element using a Server Action.

For example, the following submit button:

Expand Down Expand Up @@ -731,7 +731,7 @@ Use `useOptimistic` to optimistically update the UI before the Server Action fin
```tsx filename="app/page.tsx" switcher
'use client'

import { experimental_useOptimistic as useOptimistic } from 'react'
import { useOptimistic } from 'react'
import { send } from './actions'

type Message = {
Expand Down Expand Up @@ -770,7 +770,7 @@ export function Thread({ messages }: { messages: Message[] }) {
```jsx filename="app/page.jsx" switcher
'use client'

import { experimental_useOptimistic as useOptimistic } from 'react'
import { useOptimistic } from 'react'
import { send } from './actions'

export function Thread({ messages }) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,4 @@ This means the Client Component JavaScript bundle is downloaded and parsed. Once

Sometimes, after you've declared the `"use client"` boundary, you may want to go back to the server environment. For example, you may want to reduce the client bundle size, fetch data on the server, or use an API that is only available on the server.

You can keep code on the server even though it's theoretically nested inside Client Components by interleaving Client and Server Components and Server Actions. See the [Composition Patterns](/docs/app/building-your-application/rendering/composition-patterns) page for more information.
You can keep code on the server even though it's theoretically nested inside Client Components by interleaving Client and Server Components and [Server Actions](/docs/app/building-your-application/data-fetching/forms-and-mutations). See the [Composition Patterns](/docs/app/building-your-application/rendering/composition-patterns) page for more information.
28 changes: 2 additions & 26 deletions docs/02-app/01-building-your-application/04-caching/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ The following table provides an overview of how different Next.js APIs affect ca
| [`headers`, `useSearchParams`, `searchParams`](#dynamic-functions) | | Opt out | | |
| [`generateStaticParams`](#generatestaticparams) | | Cache | | |
| [`React.cache`](#react-cache-function) | | | | Cache |
| [`unstable_cache`](#unstable_cache) (Coming Soon) | | | | |
| [`unstable_cache`](/docs/app/api-reference/functions/unstable_cache) | | | | |

### `<Link>`

Expand Down Expand Up @@ -480,7 +480,7 @@ See the [`fetch` API reference](/docs/app/api-reference/functions/fetch) for mor

Next.js has a cache tagging system for fine-grained data caching and revalidation.

1. When using `fetch` or `unstable_cache`, you have the option to tag cache entries with one or more tags.
1. When using `fetch` or [`unstable_cache`](/docs/app/api-reference/functions/unstable_cache), you have the option to tag cache entries with one or more tags.
2. Then, you can call `revalidateTag` to purge the cache entries associated with that tag.

For example, you can set a tag when fetching data:
Expand Down Expand Up @@ -577,27 +577,3 @@ export const getItem = cache(async (id) => {
return item
})
```

### `unstable_cache`

`unstable_cache` is an experimental API for adding values to the Data Cache when the `fetch` API is not suitable. For example, when using database clients, CMS clients, or GraphQL.

```jsx
import { unstable_cache } from 'next/cache'

export default async function Page() {
const cachedData = await unstable_cache(
async () => {
const data = await db.query('...')
return data
},
['cache-key'],
{
tags: ['a', 'b', 'c'],
revalidate: 10,
}
)()
}
```

> **Warning**: This API is being developed, and we do not recommend using it in production. It's listed here to show the future direction of the Data Cache.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ related:
links:
- app/api-reference/functions/generate-metadata
- app/api-reference/file-conventions/metadata
- app/api-reference/functions/generate-viewport
---

Next.js has a Metadata API that can be used to define your application metadata (e.g. `meta` and `link` tags inside your HTML `head` element) for improved SEO and web shareability.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Metadata helps search engines understand your content better (which can result i

The Metadata API in Next.js allows you to modify the `<head>` element of a page. You can configure metadata in two ways:

- **Config-based Metadata**: Export a static metadata object or a dynamic generateMetadata function in a `layout.js` or `page.js` file.
- **Config-based Metadata**: Export a [static `metadata` object](/docs/app/api-reference/functions/generate-metadata#metadata-object) or a dynamic [`generateMetadata` function](/docs/app/api-reference/functions/generate-metadata#generatemetadata-function) in a `layout.js` or `page.js` file.
- **File-based Metadata**: Add static or dynamically generated special files to route segments.

Additionally, you can create dynamic Open Graph Images using JSX and CSS with [imageResponse](/docs/app/api-reference/functions/image-response) constructor.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ export const dynamic = 'error'

With a static export, Next.js can be deployed and hosted on any web server that can serve HTML/CSS/JS static assets.

When running `next build`, Next.js generates the static export into the `out` folder. Using `next export` is no longer needed. For example, let's say you have the following routes:
When running `next build`, Next.js generates the static export into the `out` folder. For example, let's say you have the following routes:

- `/`
- `/blog/[id]`
Expand Down Expand Up @@ -365,5 +365,6 @@ server {

| Version | Changes |
| --------- | -------------------------------------------------------------------------------------------------------------------- |
| `v14.0.0` | `next export` has been removed in favor of `"output": "export"` |
| `v13.4.0` | App Router (Stable) adds enhanced static export support, including using React Server Components and Route Handlers. |
| `v13.3.0` | `next export` is deprecated and replaced with `"output": "export"` |
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ Replacing `<transform>` and `<path>` with appropriate values.
npx @next/codemod@latest next-og-import.
```

This codemo migrates the import path of `ImageResponse` from `'next/server'` to `'next/og'`
This codemod moves transforms imports from `next/server` to `next/og` for usage of [Dynamic OG Image Generation](/docs/app/building-your-application/optimizing/metadata#dynamic-image-generation).

For example:

```js
import { ImageResponse } from 'next/server'
```

Transform into:
Transforms into:

```js
import { ImageResponse } from 'next/og'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ This guide will help you:

### Node.js Version

The minimum Node.js version is now **v16.14**. See the [Node.js documentation](https://nodejs.org/docs/latest-v16.x/api/) for more information.
The minimum Node.js version is now **v18.17**. See the [Node.js documentation](https://nodejs.org/docs/latest-v18.x/api/) for more information.

### Next.js Version

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export default function Icon() {
```

```jsx filename="app/icon.js" switcher
import { ImageResponse } from 'next/server'
import { ImageResponse } from 'next/og'

// Route segment config
export const runtime = 'edge'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export default async function Image() {
```

```jsx filename="app/about/opengraph-image.js" switcher
import { ImageResponse } from 'next/server'
import { ImageResponse } from 'next/og'

// Route segment config
export const runtime = 'edge'
Expand Down
Loading

0 comments on commit 92b4d67

Please sign in to comment.