diff --git a/docs/02-app/02-api-reference/01-directives/index.mdx b/docs/02-app/02-api-reference/01-directives/index.mdx new file mode 100644 index 0000000000000..fc836f6674354 --- /dev/null +++ b/docs/02-app/02-api-reference/01-directives/index.mdx @@ -0,0 +1,6 @@ +--- +title: Directives +description: Directives are used to modify the behavior of your Next.js application. +--- + +The following directives are available: \ No newline at end of file diff --git a/docs/02-app/02-api-reference/01-directives/use-cache.mdx b/docs/02-app/02-api-reference/01-directives/use-cache.mdx new file mode 100644 index 0000000000000..f667bb3177af2 --- /dev/null +++ b/docs/02-app/02-api-reference/01-directives/use-cache.mdx @@ -0,0 +1,381 @@ +--- +title: use cache +description: Learn how to use the use cache directive to cache data in your Next.js application. +version: experimental +related: + title: Related + description: View related API references. + links: + - app/api-reference/next-config-js/dynamicIO + - app/api-reference/next-config-js/cacheLife + - app/api-reference/functions/cacheTag + - app/api-reference/functions/revalidateTag + - app/api-reference/functions/unstable_cache +--- + +The `use cache` directive designates a component, function, or file to be cached. It can be used at the top of a file to indicate that all functions in the file are cacheable, or inline at the top of a function to mark the function as cacheable. This is an experimental Next.js feature, and not a native React feature like `use client` or `use server`. + +Enable support for the `use cache` directive with the `dynamicIO` flag in your `next.config.ts` file: + +```ts filename="next.config.ts" +import type { NextConfig } from 'next'; + +const nextConfig: NextConfig = { + experimental: { + dynamicIO: true, + } +}; + +export default nextConfig; +``` + +> The `use cache` directive will be available separately from the`dynamicIO` flag in the future. + +Caching is a technique to improve the performance of web applications by storing the results of computations or data fetches. In Next.js you can use caching to optimize your applications rendering performance. + +To explicitly cache certain asynchronous operations and achieve static behavior, you can use the `use cache` directive. This allows you to optimize rendering performance by caching results from async data requests, while still enabling dynamic rendering when needed. + +The `use cache` directive is an experimental feature that aims to replace the [`unstable_cache`](/docs/app/api-reference/functions/unstable_cache) function. Unlike `unstable_cache`, which is limited to caching JSON data and requires manual definition of revalidation periods and tags, `use cache` offers more flexibility. It allows you to cache a wider range of data, including anything that React Server Components (RSC) can serialize, as well as data-fetching outputs and component outputs. + +Additionally, `use cache` automatically manages complexities by tracking both inputs and outputs, making it less likely for you to accidentally poison your cache. Since it serializes both inputs and outputs, you can avoid issues with incorrect cache retrieval. + +## `use cache` directive + +The Next.js `use cache` directive allows you to cache entire routes, components, and the return value of functions. When you have an asynchronous function, you can mark it as cacheable by adding `use cache` at the top of the file or inside the function scope. This informs Next.js that the return value can be cached and reused for subsequent renders. + +```tsx +// File level +"use cache" + +export default async function Page() { + // ... +} + +// Component level +export async function MyComponent() { + "use cache" + return <> +} + +// Function level +export async function getData() { + "use cache" + const data = await fetch('/api/data') + return data +} +``` + +> **Good to know**: Functions that use the `use cache` directive must not have any side-effects, such as modifying state, directly manipulating the DOM, or setting timers to execute code at intervals + +## Revalidating + +By default when using the `use cache` directive Next.js sets a **[revalidation period](/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#revalidating-data) of fifteen minutes** with a near infinite expiration duration, meaning it's suitable for content that doesn't need frequent updates. + +While this may be useful for content you don't expect to change often, you can use the `cacheLife` and `cacheTag` APIs for more granular caching control: + +- [`cacheLife`](#time-based-revalidation-with-cachelife): For time-based revalidation periods. +- [`cacheTag`](#revalidate-on-demand-with-cachetag): For on-demand revalidation. + +Both of these APIs integrate across the client and server caching layers, meaning you can configure your caching semantics in one place and have them apply everywhere. + +**Basic example**: + +The example below shows how to use the `cacheLife` function at the function level to set a revalidation period of one day on the functions output: + +```tsx filename="app/components/my-component.tsx" highlight={1,5,6} +import { unstable_cacheLife as cacheLife} from 'next/cache' + +export async function MyComponent() { + async function getData() { + "use cache" + cacheLife('days') + const data = await fetch('/api/data'); + return data; + } + + return // Use the data here +} +``` + +### How cache revalidation works + +When a revalidation period of fifteen minutes is set, the following happens: + +1. **Cache HIT**: If a request is made within the 15 minute window, the cached data is served, and is a cache HIT. +2. **Stale data**: If the request happens after 15 minutes the cached value is still served, but is now considered stale. Next.js will recompute a new cache entry in the background. +3. **Cache MISS**: If the cache entry expires and a subsequent request is made, then Next.js will treat this as a cache MISS, and the data will be recomputed and fetched again from the source. + +## Time-based revalidation with `cacheLife` + +The `cacheLife` function can only be used where the `use cache` directive is present, and allows you to define time-based revalidation periods based on cache profiles. + +We recommend always adding a cache profile when using the `use cache` directive to explicitly define caching behavior. + +Cache profiles are objects that contain the following properties: + +| **Property** | **Value** | **Description** | **Requirement** | +| --- | --- | --- | --- | +| `stale` | `number` | Duration the client should cache a value without checking the server. | Optional | +| `revalidate` | `number` | Frequency at which the cache should refresh on the server; stale values may be served while revalidating. | Optional | +| `expire` | `number` | Maximum duration for which a value can remain stale before switching to dynamic fetching; must be longer than `revalidate`. | Optional - Must be longer than `revalidate` | + +The "stale" property differs from the [`staleTimes`](/docs/app/api-reference/next-config-js/staleTimes) setting in that it specifically controls client-side router caching. While `staleTimes` is a global setting that affects all instances of both dynamic and static data, the `cacheLife` configuration allows you to define "stale" times on a per-function or per-route basis. + +> **Good to know**: The “stale” property does not set the `Cache-control: max-age` header. It instead controls the client-side router cache. + +### Default cache profiles + +Next.js provides a set of named cache profiles modeled on various timescales. If you don't specify a cache profile in the `cacheLife` function alongside the `use cache` directive, Next.js will automatically apply the “default” cache profile. + +| **Profile** | **Stale** | **Revalidate** | **Expire** | **Description** | +| --- | --- | --- | --- | --- | +| `default` | undefined | 15 minutes | INFINITE_CACHE | Default profile, suitable for content that doesn't need frequent updates | +| `seconds` | undefined | 1 second | 1 minute | For rapidly changing content requiring near real-time updates | +| `minutes` | 5 minutes | 1 minute | 1 hour | For content that updates frequently within an hour | +| `hours` | 5 minutes | 1 hour | 1 day | For content that updates daily but can be slightly stale | +| `days` | 5 minutes | 1 day | 1 week | For content that updates weekly but can be a day old | +| `weeks` | 5 minutes | 1 week | 1 month | For content that updates monthly but can be a week old | +| `max` | 5 minutes | 1 month | INFINITE_CACHE | For very stable content that rarely needs updating | + +**Basic example**: + +```tsx filename="app/page.tsx" highlight={4} +"use cache" +import { unstable_cacheLife as cacheLife} from 'next/cache' + +cacheLife('minutes') +``` + +The string values used to reference cache profiles don't carry inherent meaning; instead they serve as semantic labels. This allows you to better understand and manage your cached content within your codebase. + +### Defining reusable cache profiles + +To create a reusable cache profile, choose a name that suits your use case. You can create as many custom cache profiles as needed. Each profile can be referenced by its name as a string value passed to the `cacheLife` function. + +```ts filename="next.config.ts" +const nextConfig = { + experimental: { + dynamicIO: true, + cacheLife: { + biweekly: { + stale: 60 * 60 * 24 * 14, // 14 days + revalidate: 60 * 60 * 24, // 1 day + expire: 86400 60 * 60 * 24 * 14, // 14 days + }, + }, + }, +} + +module.exports = nextConfig +``` + +The example above caches for 14 days, checks for updates daily, and expires the cache after 14 days. You can then reference this profile throughout your application by its name: + +```tsx filename="app/page.tsx" highlight={4} +"use cache" +import { unstable_cacheLife as cacheLife} from 'next/cache' + +cacheLife('biweekly') + +// rest of code +``` + +### Overriding the default cache profiles + +While the default cache profiles provide a useful way to think about how fresh or stale any given part of cacheable output can be, you may prefer different named profiles to better align with your applications caching strategies. + +You can override the default named cache profiles by creating a new configuration with the same name as the defaults. + +The example below shows how to override the default “days” cache profile: + +```ts filename="next.config.ts" +const nextConfig = { + experimental: { + dynamicIO: true, + cacheLife: { + days: { + stale: 3600, // 1 hour + revalidate: 900, // 15 minutes + expire: 86400 // 1 day + }, + }, + }, +} + +module.exports = nextConfig +``` + +### Defining inlining cache profiles + +For specific use cases, you can set a custom cache profile by passing an object to the `cacheLife` function: + +```tsx filename="app/page.tsx" highlight={5,6,7} +"use cache" +import { unstable_cacheLife as cacheLife} from 'next/cache' + +cacheLife({ + stale: 3600, // 1 hour + revalidate: 900, // 15 minutes + expire: 86400 // 1 day +}) + +// rest of code +``` + +This inline cache profile will only be applied to the function or file it was created in. If you want to reuse the same profile throughout your application, you can [add the configuration](#defining-reusable-cache-profiles) to the `cacheLife` property of your `next.config.ts` file. + +### Nested usage of `use cache` and `cacheLife` + +When defining multiple caching behaviors, in the same route or component tree, if the inner caches specify their own `cacheLife` profile, the outer cache will respect the shortest cache duration among them. **This applies only if the outer cache does not have its own explicit `cacheLife` profile defined.** + +**Decision hierarchy for cache boundaries:** + +1. Next.js will use the shortest cache profile found within the whole `use cache` boundary, excluding inner `use cache`directives. +2. If no cache profile exists then the shortest profile times from all inner `use cache` calls applies to this `use cache`. If there are no inner `use cache`'s then the default is used +3. Inner caches at two levels deep, do not affect the outer cache since they have already provided their duration to their parent. + +For example, if you add the `use cache` directive to your page, without specifying a cache profile, the default cache profile will be applied implicitly (`cacheLife(”default”)`). If a component imported into the page also uses the `use cache` directive with its own cache profile, the outer and inner cache profiles are compared, and shortest duration set in the profiles will be applied. + +```tsx filename="app/components/parent.tsx" highlight={5,6,19,20} +// Parent component +import { unstable_cacheLife as cacheLife} from 'next/cache' + +export async function ParentComponent() { + "use cache" + cacheLife('days') + + return ( +
+ +
+ ) +} + +// Child component +import { unstable_cacheLife as cacheLife} from 'next/cache' + +export async function ChildComponent() { + "use cache" + cacheLife('hours') + + // This component's cache will respect the shorter 'hours' profile +} +``` + +## Revalidate on-demand with `cacheTag` + +A `cacheTag` is used in combination with [`revalidateTag`](/docs/app/api-reference/functions/revalidateTag) to purge cache data, on-demand. The `cacheTag` function takes a single string value, or a string array. + +In the below example the `getData` function uses the “weeks” cache profile, and defines a `cacheTag` on the functions cached output: + +```tsx filename="app/actions.ts" highlight={4,5} +import { + unstable_cacheTag as cacheTag, + unstable_cacheLife as cacheLife +} from 'next/cache' + +export async function getData() { + "use cache" + cacheLife('weeks') + cacheTag('my-data') + + const data = await fetch('/api/data'); + return data; +} +``` + +You can then purge the cache on-demand using revalidateTag in another function, for examples, a [route handler](/docs/app/building-your-application/routing/route-handlers) or [Server Action](/docs/app/building-your-application/data-fetching/server-actions-and-mutations): + +```tsx filename="app/submit.ts" highlight={4,5} +'use server' + +import { revalidateTag } from 'next/cache' + +export default async function submit() { + await addPost() + revalidateTag('my-data') +} +``` + +See the [revalidateTag](/docs/app/api-reference/functions/revalidateTag) docs for more information on purging cached data on-demand. + +## Examples + +### Caching entire routes with `use cache` + +The placement of `Suspense` boundaries in your application determines how dynamic your components can be. Components inside a `Suspense` boundary are allowed to be dynamic, but this doesn't mean they automatically are. If you cache everything or your content is static, Next.js will still generate a static application. Using `Suspense` indicates that dynamic behavior is allowed within the boundary. + +To ensure your route remains static, avoid using `Suspense` boundaries. If you must use them, you can maintain a static page by adding the `use cache` directive to both the layout and page components as they are treated as separate entry points in your application. + +This is recommended for applications that previously used the [`export const dynamic = "force-cache"`](/docs/app/building-your-application/caching#opting-out-1) option, and will ensure the entire route is prerendered. + +```tsx filename="app/layout.tsx" +"use cache" +import { unstable_cacheLife as cacheLife} from 'next/cache' +cacheLife('minutes') + +export default Layout({children}: {children: ReactNode}) { + return
{children}
+} +``` +And in your `page.tsx` file you can add the `use cache` directive to the top of the file, and define a cache profile: + +```tsx filename="app/page.tsx" +"use cache" +import { unstable_cacheLife as cacheLife} from 'next/cache' +cacheLife('minutes') + +async function Users() { + const users = await fetch('/api/users'); + // loop through users +} + +export default Page() { + return ( +
+ +
+ ) +} +``` + +### Caching component output with `use cache` + +You can use `use cache` at the component level to cache any fetches or computations performed within that component. When you reuse the component throughout your application it can share the same cache entry as long as the props maintain the same structure. + +The props are serialized and form part of the cache key. If you use the same component in multiple places in your application, the cache entry will be reused as long as the serialized props produce the same value in each instance. + +```tsx filename="app/components/bookings.tsx" highlight={4,5} +import { unstable_cacheLife as cacheLife} from 'next/cache' + +interface BookingsProps { + type: string +} + +export async function Bookings({type = 'massage'}: BookingsProps) { + "use cache" + cacheLife('minutes') + + async function getBookingsData() { + const data = await fetch(`/api/bookings?type=${encodeURIComponent(type)}`); + return data; + } + return //... +} +``` + +### Caching function output with `use cache` + +Since you can add `use cache` to any asynchronous function you aren't limited to caching components or routes only. You might want to cache a network request or database query or compute something that is very slow. By adding `use cache` to a function containing this type of work it becomes cacheable, and when reused, will share the same cache entry. + +```tsx filename="app/actions.ts" highlight={4,5} +import { unstable_cacheLife as cacheLife} from 'next/cache' + +export async function getData() { + "use cache" + cacheLife('minutes') + + const data = await fetch('/api/data'); + return data; +} +``` diff --git a/docs/02-app/02-api-reference/01-directives/use-client.mdx b/docs/02-app/02-api-reference/01-directives/use-client.mdx new file mode 100644 index 0000000000000..51030a600892f --- /dev/null +++ b/docs/02-app/02-api-reference/01-directives/use-client.mdx @@ -0,0 +1,95 @@ +--- +title: use client +description: Learn how to use the use client directive to render a component on the client. +related: + description: React documentation for use client. + links: + - https://react.dev/reference/rsc/use-client +--- + +The `use client` directive designates a component to be rendered on the **client side** and should be used when creating interactive user interfaces (UI) that require client-side JavaScript capabilities, such as state management, event handling, and access to browser APIs. This is a React feature. + +## Usage + +To designate a component as a Client Component, add the `use client` directive **at the top of the file**, before any imports: + +````tsx filename="app/components/counter.tsx" highlight={1} switcher +'use client' + +import { useState } from 'react' + +export default function Counter() { + const [count, setCount] = useState(0) + + return ( +
+

Count: {count}

+ +
+ ) +} +```` + +````jsx filename="app/components/counter.js" highlight={1} switcher +'use client' + +import { useState } from 'react' + +export default function Counter() { + const [count, setCount] = useState(0) + + return ( +
+

Count: {count}

+ +
+ ) +} +```` + +## Nesting Client Components within Server Components + +Combining Server and Client Components allows you to build applications that are both performant and interactive: + +1. **Server Components**: Use for static content, data fetching, and SEO-friendly elements. +2. **Client Components**: Use for interactive elements that require state, effects, or browser APIs. +3. **Component composition**: Nest Client Components within Server Components as needed for a clear separation of server and client logic. + +In the following example: + +- `Header` is a Server Component handling static content. +- `Counter` is a Client Component enabling interactivity within the page. + +```tsx filename="app/page.tsx" highlight={2,8} switcher +import Header from './header' +import Counter from './counter' // This is a Client Component + +export default function Page() { + return ( +
+
+ +
+ ) +} +``` + +```jsx filename="app/page.js" highlight={2,8} switcher +import Header from './header' +import Counter from './counter' // This is a Client Component + +export default function Page() { + return ( +
+
+ +
+ ) +} +``` + + +## Reference + +See the [React documentation](https://react.dev/reference/rsc/use-client) for more information on `use client`. + diff --git a/docs/02-app/02-api-reference/01-directives/use-server.mdx b/docs/02-app/02-api-reference/01-directives/use-server.mdx new file mode 100644 index 0000000000000..73fa1d73642e3 --- /dev/null +++ b/docs/02-app/02-api-reference/01-directives/use-server.mdx @@ -0,0 +1,158 @@ +--- +title: use server +description: Learn how to use the use server directive to execute code on the server. +related: + description: React documentation for use server. + links: + - https://react.dev/reference/rsc/use-server +--- + +The `use server` directive designates a function or file to be executed on the **server side**. It can be used at the top of a file to indicate that all functions in the file are server-side, or inline at the top of a function to mark the function as a [Server Function](https://19.react.dev/reference/rsc/server-functions). This is a React feature. + +## Using `use server` at the top of a file + +The following example shows a file with a `use server` directive at the top. All functions in the file are executed on the server. + +```tsx filename="app/actions.ts" highlight={1} switcher +'use server' +import { db } from '@/lib/db' // Your database client + +export async function createUser(data: { name: string; email: string }) { + const user = await db.user.create({ data }) + return user +} +``` + +```jsx filename="app/actions.js" highlight={1} switcher +'use server' +import { db } from '@/lib/db' // Your database client + +export async function createUser(data) { + const user = await db.user.create({ data }) + return user +} +``` + +### Using Server Functions in a Client Component + +To use Server Functions in Client Components you need to create your Server Functions in a dedicated file using the `use server` directive at the top of the file. These Server Functions can then be imported into Client and Server Components and executed. + +Assuming you have a `fetchUsers` Server Function in `actions.ts`: + +```tsx filename="app/actions.ts" highlight={1} switcher +'use server' +import { db } from '@/lib/db' // Your database client + +export async function fetchUsers() { + const users = await db.user.findMany() + return users +} +``` + +```jsx filename="app/actions.js" highlight={1} switcher +'use server' +import { db } from '@/lib/db' // Your database client + +export async function fetchUsers() { + const users = await db.user.findMany() + return users +} +``` + +Then you can import the `fetchUsers` Server Function into a Client Component and execute it on the client-side. + +```tsx filename="app/components/my-button.tsx" highlight={1,2,8} switcher +'use client' +import { fetchUsers } from '../actions' + +export default function MyButton() { + return +} +``` + +```jsx filename="app/components/my-button.js" highlight={1,2,8} switcher +'use client' +import { fetchUsers } from '../actions' + +export default function MyButton() { + return +} +``` + + +## Using `use server` inline + +In the following example, `use server` is used inline at the top of a function to mark it as a [Server Function](https://19.react.dev/reference/rsc/server-functions): + +```tsx filename="app/page.tsx" highlight={5} switcher +import { db } from '@/lib/db' // Your database client + +export default function UserList() { + async function fetchUsers() { + 'use server' + const users = await db.user.findMany() + return users + } + + return +} +``` + +```jsx filename="app/page.js" highlight={5} switcher +import { db } from '@/lib/db' // Your database client + +export default function UserList() { + async function fetchUsers() { + 'use server' + const users = await db.user.findMany() + return users + } + + return +} +``` + +## Security considerations + +When using the `use server` directive, it's important to ensure that all server-side logic is secure and that sensitive data remains protected. + +### Authentication and authorization + +Always authenticate and authorize users before performing sensitive server-side operations. + +```tsx filename="app/actions.ts" highlight={1,7,8,9,10} switcher +'use server' + +import { db } from '@/lib/db' // Your database client +import { authenticate } from '@/lib/auth' // Your authentication library + +export async function createUser(data: { name: string; email: string }, token: string) { + const user = authenticate(token) + if (!user) { + throw new Error('Unauthorized') + } + const newUser = await db.user.create({ data }) + return newUser +} +``` + +```jsx filename="app/actions.js" highlight={1,7,8,9,10} switcher +'use server' + +import { db } from '@/lib/db' // Your database client +import { authenticate } from '@/lib/auth' // Your authentication library + +export async function createUser(data, token) { + const user = authenticate(token) + if (!user) { + throw new Error('Unauthorized') + } + const newUser = await db.user.create({ data }) + return newUser +} +``` + + +## Reference + +See the [React documentation](https://react.dev/reference/rsc/use-server) for more information on `use server`. diff --git a/docs/02-app/02-api-reference/01-components/font.mdx b/docs/02-app/02-api-reference/02-components/font.mdx similarity index 100% rename from docs/02-app/02-api-reference/01-components/font.mdx rename to docs/02-app/02-api-reference/02-components/font.mdx diff --git a/docs/02-app/02-api-reference/01-components/form.mdx b/docs/02-app/02-api-reference/02-components/form.mdx similarity index 100% rename from docs/02-app/02-api-reference/01-components/form.mdx rename to docs/02-app/02-api-reference/02-components/form.mdx diff --git a/docs/02-app/02-api-reference/01-components/image.mdx b/docs/02-app/02-api-reference/02-components/image.mdx similarity index 100% rename from docs/02-app/02-api-reference/01-components/image.mdx rename to docs/02-app/02-api-reference/02-components/image.mdx diff --git a/docs/02-app/02-api-reference/01-components/index.mdx b/docs/02-app/02-api-reference/02-components/index.mdx similarity index 100% rename from docs/02-app/02-api-reference/01-components/index.mdx rename to docs/02-app/02-api-reference/02-components/index.mdx diff --git a/docs/02-app/02-api-reference/01-components/link.mdx b/docs/02-app/02-api-reference/02-components/link.mdx similarity index 100% rename from docs/02-app/02-api-reference/01-components/link.mdx rename to docs/02-app/02-api-reference/02-components/link.mdx diff --git a/docs/02-app/02-api-reference/01-components/script.mdx b/docs/02-app/02-api-reference/02-components/script.mdx similarity index 100% rename from docs/02-app/02-api-reference/01-components/script.mdx rename to docs/02-app/02-api-reference/02-components/script.mdx diff --git a/docs/02-app/02-api-reference/02-file-conventions/01-metadata/app-icons.mdx b/docs/02-app/02-api-reference/03-file-conventions/01-metadata/app-icons.mdx similarity index 100% rename from docs/02-app/02-api-reference/02-file-conventions/01-metadata/app-icons.mdx rename to docs/02-app/02-api-reference/03-file-conventions/01-metadata/app-icons.mdx diff --git a/docs/02-app/02-api-reference/02-file-conventions/01-metadata/index.mdx b/docs/02-app/02-api-reference/03-file-conventions/01-metadata/index.mdx similarity index 100% rename from docs/02-app/02-api-reference/02-file-conventions/01-metadata/index.mdx rename to docs/02-app/02-api-reference/03-file-conventions/01-metadata/index.mdx diff --git a/docs/02-app/02-api-reference/02-file-conventions/01-metadata/manifest.mdx b/docs/02-app/02-api-reference/03-file-conventions/01-metadata/manifest.mdx similarity index 100% rename from docs/02-app/02-api-reference/02-file-conventions/01-metadata/manifest.mdx rename to docs/02-app/02-api-reference/03-file-conventions/01-metadata/manifest.mdx diff --git a/docs/02-app/02-api-reference/02-file-conventions/01-metadata/opengraph-image.mdx b/docs/02-app/02-api-reference/03-file-conventions/01-metadata/opengraph-image.mdx similarity index 100% rename from docs/02-app/02-api-reference/02-file-conventions/01-metadata/opengraph-image.mdx rename to docs/02-app/02-api-reference/03-file-conventions/01-metadata/opengraph-image.mdx diff --git a/docs/02-app/02-api-reference/02-file-conventions/01-metadata/robots.mdx b/docs/02-app/02-api-reference/03-file-conventions/01-metadata/robots.mdx similarity index 100% rename from docs/02-app/02-api-reference/02-file-conventions/01-metadata/robots.mdx rename to docs/02-app/02-api-reference/03-file-conventions/01-metadata/robots.mdx diff --git a/docs/02-app/02-api-reference/02-file-conventions/01-metadata/sitemap.mdx b/docs/02-app/02-api-reference/03-file-conventions/01-metadata/sitemap.mdx similarity index 100% rename from docs/02-app/02-api-reference/02-file-conventions/01-metadata/sitemap.mdx rename to docs/02-app/02-api-reference/03-file-conventions/01-metadata/sitemap.mdx diff --git a/docs/02-app/02-api-reference/02-file-conventions/default.mdx b/docs/02-app/02-api-reference/03-file-conventions/default.mdx similarity index 100% rename from docs/02-app/02-api-reference/02-file-conventions/default.mdx rename to docs/02-app/02-api-reference/03-file-conventions/default.mdx diff --git a/docs/02-app/02-api-reference/02-file-conventions/error.mdx b/docs/02-app/02-api-reference/03-file-conventions/error.mdx similarity index 100% rename from docs/02-app/02-api-reference/02-file-conventions/error.mdx rename to docs/02-app/02-api-reference/03-file-conventions/error.mdx diff --git a/docs/02-app/02-api-reference/02-file-conventions/index.mdx b/docs/02-app/02-api-reference/03-file-conventions/index.mdx similarity index 100% rename from docs/02-app/02-api-reference/02-file-conventions/index.mdx rename to docs/02-app/02-api-reference/03-file-conventions/index.mdx diff --git a/docs/02-app/02-api-reference/02-file-conventions/instrumentation.mdx b/docs/02-app/02-api-reference/03-file-conventions/instrumentation.mdx similarity index 100% rename from docs/02-app/02-api-reference/02-file-conventions/instrumentation.mdx rename to docs/02-app/02-api-reference/03-file-conventions/instrumentation.mdx diff --git a/docs/02-app/02-api-reference/02-file-conventions/layout.mdx b/docs/02-app/02-api-reference/03-file-conventions/layout.mdx similarity index 100% rename from docs/02-app/02-api-reference/02-file-conventions/layout.mdx rename to docs/02-app/02-api-reference/03-file-conventions/layout.mdx diff --git a/docs/02-app/02-api-reference/02-file-conventions/loading.mdx b/docs/02-app/02-api-reference/03-file-conventions/loading.mdx similarity index 100% rename from docs/02-app/02-api-reference/02-file-conventions/loading.mdx rename to docs/02-app/02-api-reference/03-file-conventions/loading.mdx diff --git a/docs/02-app/02-api-reference/02-file-conventions/mdx-components.mdx b/docs/02-app/02-api-reference/03-file-conventions/mdx-components.mdx similarity index 100% rename from docs/02-app/02-api-reference/02-file-conventions/mdx-components.mdx rename to docs/02-app/02-api-reference/03-file-conventions/mdx-components.mdx diff --git a/docs/02-app/02-api-reference/02-file-conventions/middleware.mdx b/docs/02-app/02-api-reference/03-file-conventions/middleware.mdx similarity index 100% rename from docs/02-app/02-api-reference/02-file-conventions/middleware.mdx rename to docs/02-app/02-api-reference/03-file-conventions/middleware.mdx diff --git a/docs/02-app/02-api-reference/02-file-conventions/not-found.mdx b/docs/02-app/02-api-reference/03-file-conventions/not-found.mdx similarity index 100% rename from docs/02-app/02-api-reference/02-file-conventions/not-found.mdx rename to docs/02-app/02-api-reference/03-file-conventions/not-found.mdx diff --git a/docs/02-app/02-api-reference/02-file-conventions/page.mdx b/docs/02-app/02-api-reference/03-file-conventions/page.mdx similarity index 100% rename from docs/02-app/02-api-reference/02-file-conventions/page.mdx rename to docs/02-app/02-api-reference/03-file-conventions/page.mdx diff --git a/docs/02-app/02-api-reference/02-file-conventions/route-segment-config.mdx b/docs/02-app/02-api-reference/03-file-conventions/route-segment-config.mdx similarity index 98% rename from docs/02-app/02-api-reference/02-file-conventions/route-segment-config.mdx rename to docs/02-app/02-api-reference/03-file-conventions/route-segment-config.mdx index 4c9348493c9ed..e4755bc11b335 100644 --- a/docs/02-app/02-api-reference/02-file-conventions/route-segment-config.mdx +++ b/docs/02-app/02-api-reference/03-file-conventions/route-segment-config.mdx @@ -3,6 +3,8 @@ title: Route Segment Config description: Learn about how to configure options for Next.js route segments. --- +> The options outlined on this page are disabled if the [`dynamicIO`](/docs/app/api-reference/next-config-js/dynamicIO) flag is on, and will eventually be deprecated in the future. + The Route Segment options allows you to configure the behavior of a [Page](/docs/app/building-your-application/routing/layouts-and-templates), [Layout](/docs/app/building-your-application/routing/layouts-and-templates), or [Route Handler](/docs/app/building-your-application/routing/route-handlers) by directly exporting the following variables: | Option | Type | Default | diff --git a/docs/02-app/02-api-reference/02-file-conventions/route.mdx b/docs/02-app/02-api-reference/03-file-conventions/route.mdx similarity index 100% rename from docs/02-app/02-api-reference/02-file-conventions/route.mdx rename to docs/02-app/02-api-reference/03-file-conventions/route.mdx diff --git a/docs/02-app/02-api-reference/02-file-conventions/template.mdx b/docs/02-app/02-api-reference/03-file-conventions/template.mdx similarity index 100% rename from docs/02-app/02-api-reference/02-file-conventions/template.mdx rename to docs/02-app/02-api-reference/03-file-conventions/template.mdx diff --git a/docs/02-app/02-api-reference/04-functions/cacheTag.mdx b/docs/02-app/02-api-reference/04-functions/cacheTag.mdx new file mode 100644 index 0000000000000..9c26f7e711dc3 --- /dev/null +++ b/docs/02-app/02-api-reference/04-functions/cacheTag.mdx @@ -0,0 +1,131 @@ +--- +title: cacheTag +description: Learn how to use the cacheTag function to manage cache invalidation in your Next.js application. +version: experimental +related: + title: Related + description: View related API references. + links: + - app/api-reference/next-config-js/dynamicIO + - app/api-reference/directives/use-cache + - app/api-reference/functions/revalidateTag +--- + +The `cacheTag` function allows you to tag cached data for on-demand invalidation. By associating tags with cache entries, you can selectively purge or revalidate specific parts of your cache without affecting other cached data. + +## Usage + +To use `cacheTag`, enable the [`dynamicIO` flag](/docs/app/api-reference/next-config-js/dynamicIO) in your `next.config.js` and import `cacheTag` from `next/cache`: + +```ts filename="next.config.ts" +import type { NextConfig } from 'next'; + +const nextConfig: NextConfig = { + experimental: { + dynamicIO: true, + } +}; + +export default nextConfig; +``` + +```tsx filename="app/actions.ts" +import { unstable_cacheTag as cacheTag } from 'next/cache' + +export async function getData() { + "use cache" + cacheTag('my-data') + const data = await fetch('/api/data') + return data +} +``` + +## Combining with `revalidateTag` + +Use `cacheTag` in conjunction with `revalidateTag` to purge tagged cache entries on-demand. This is useful for scenarios like updating data after a mutation or an external event. + +```tsx filename="app/submit.ts" +'use server' + +import { revalidateTag } from 'next/cache' + +export default async function submit() { + await addPost() + revalidateTag('my-data') +} +``` + +## Examples + +### Tagging cached data + +Tag your cached data by calling `cacheTag` within a cached function or component: + +```tsx filename="app/components/bookings.tsx" +import { unstable_cacheTag as cacheTag, unstable_cacheLife as cacheLife } from 'next/cache' + + +interface BookingsProps { + type: string +} + +export async function Bookings({type = 'massage'}: BookingsProps) { + "use cache" + cacheLife('minutes') + cacheTag('bookings-data') + + async function getBookingsData() { + const data = await fetch(`/api/bookings?type=${encodeURIComponent(type)}`) + return data + } + + return //... +} +``` + +### Tagging using data + +You can use the data returned from an async function to tag the cache entry. + +```tsx filename="app/components/bookings.tsx" +import { unstable_cacheTag as cacheTag, unstable_cacheLife as cacheLife } from 'next/cache' + +interface BookingsProps { + type: string +} + +export async function Bookings({type = 'massage'}: BookingsProps) { + async function getBookingsData() { + "use cache" + cacheLife('minutes') + const data = await fetch(`/api/bookings?type=${encodeURIComponent(type)}`) + cacheTag('bookings-data', data.id) + return data + } + return //... +} +``` + +### Invalidating tagged cache + +Invalidate the cache for a specific tag when needed: + +```tsx filename="app/actions.ts" +'use server' + +import { revalidateTag } from 'next/cache' + +export async function updateBookings() { + await updateBookingData() + revalidateTag('bookings-data') +} +``` + +## Notes + +- **Idempotent Tags**: Applying the same tag multiple times has no additional effect. +- **Multiple Tags**: You can assign multiple tags to a single cache entry by passing an array to `cacheTag`. + +```tsx +cacheTag(['tag-one', 'tag-two']) +``` diff --git a/docs/02-app/02-api-reference/05-next-config-js/cacheLife.mdx b/docs/02-app/02-api-reference/05-next-config-js/cacheLife.mdx new file mode 100644 index 0000000000000..eb9eb8906bdbb --- /dev/null +++ b/docs/02-app/02-api-reference/05-next-config-js/cacheLife.mdx @@ -0,0 +1,49 @@ +--- +title: cacheLife +description: Learn how to set up cacheLife configurations in Next.js. +version: experimental +--- + +The `cacheLife` option allows you to define custom configurations when using the `cacheLife` function with the [`use cache` directive](/docs/app/api-reference/directives/use-cache) at the level of components, functions or files, for more granular control over caching. + +## Usage + +To use `cacheLife`, enable the [`dynamicIO` flag](/docs/app/api-reference/next-config-js/dynamicIO) and define the configuration in your `next.config.js` file as follows: + +```js filename="next.config.js" +module.exports = { + experimental: { + dynamicIO: true, + cacheLife: { + blog: { + stale: 3600, // 1 hour + revalidate: 900, // 15 minutes + expire: 86400 // 1 day + }, + }, + } +} +``` + +You can now use this custom `blog` configuration in your component, function or file as follows: + +```tsx filename="app/actions.ts" highlight={4,5} +import { unstable_cacheLife as cacheLife} from 'next/cache' + +export async function getCachedData() { + "use cache" + cacheLife('blog') + const data = await fetch('/api/data') + return data +} +``` + +## Configuration structure + +The configuration object has key values with the following format: + +| **Property** | **Value** | **Description** | **Requirement** | +| --- | --- | --- | --- | +| `stale` | `number` | Duration the client should cache a value without checking the server. | Optional | +| `revalidate` | `number` | Frequency at which the cache should refresh on the server; stale values may be served while revalidating. | Optional | +| `expire` | `number` | Maximum duration for which a value can remain stale before switching to dynamic fetching; must be longer than `revalidate`. | Optional - Must be longer than `revalidate` | \ No newline at end of file diff --git a/docs/02-app/02-api-reference/05-next-config-js/dynamicIO.mdx b/docs/02-app/02-api-reference/05-next-config-js/dynamicIO.mdx new file mode 100644 index 0000000000000..fee689d2b34c9 --- /dev/null +++ b/docs/02-app/02-api-reference/05-next-config-js/dynamicIO.mdx @@ -0,0 +1,37 @@ +--- +title: dynamicIO +description: Learn how to enable the dynamicIO flag in Next.js. +version: experimental +--- + +The `dynamicIO` flag is an experimental feature in Next.js that causes data fetching operations in the App Router to be excluded from pre-renders unless they are explicitly cached. This can be useful for optimizing the performance of dynamic data fetching in server components. + +It is useful if your application requires fresh data fetching during runtime rather than serving from a pre-rendered cache. + +It is expected to be used in conjunction with [`use cache`](/docs/app/api-reference/directives/use-cache) so that your data fetching happens at runtime by default unless you define specific parts of your application to be cached with `use cache` at the page, function, or component level. + +## Usage + +To enable the `dynamicIO` flag, set it to `true` in the `experimental` section of your `next.config.ts` file: + +```ts filename="next.config.ts" +import type { NextConfig } from 'next'; + +const nextConfig: NextConfig = { + experimental: { + dynamicIO: true, + } +}; + +export default nextConfig; +``` + +When `dynamicIO` is enabled, you can use the following cache functions and configurations: + +- The [`use cache` directive](/docs/app/api-reference/directives/use-cache) +- The [`cacheLife` function](/docs/app/api-reference/next-config-js/cacheLife) with `use cache` +- The [`cacheTag` function](/docs/app/api-reference/functions/cacheTag) + +## Notes + +- While `dynamicIO` can optimize performance by ensuring fresh data fetching during runtime, it may also introduce additional latency compared to serving pre-rendered content. \ No newline at end of file diff --git a/docs/02-app/02-api-reference/08-legacy-apis/index.mdx b/docs/02-app/02-api-reference/08-legacy-apis/index.mdx new file mode 100644 index 0000000000000..224eb1426712d --- /dev/null +++ b/docs/02-app/02-api-reference/08-legacy-apis/index.mdx @@ -0,0 +1,6 @@ +--- +title: Legacy APIs +description: API Reference for Next.js Legacy APIs. +--- + +The following APIs are considered legacy and will be removed in a future version of Next.js: diff --git a/docs/02-app/02-api-reference/04-functions/unstable_cache.mdx b/docs/02-app/02-api-reference/08-legacy-apis/unstable_cache.mdx similarity index 95% rename from docs/02-app/02-api-reference/04-functions/unstable_cache.mdx rename to docs/02-app/02-api-reference/08-legacy-apis/unstable_cache.mdx index 3aad5affe0d81..87676e854368c 100644 --- a/docs/02-app/02-api-reference/04-functions/unstable_cache.mdx +++ b/docs/02-app/02-api-reference/08-legacy-apis/unstable_cache.mdx @@ -4,6 +4,8 @@ description: API Reference for the unstable_cache function. version: unstable --- +> This API will be deprecated in future versions. In version 15 we recommend using the [`use cache`](app/api-reference/directives/use-cache) directive instead. + `unstable_cache` allows you to cache the results of expensive operations, like database queries, and reuse them across multiple requests. ```jsx diff --git a/docs/02-app/02-api-reference/04-functions/unstable_noStore.mdx b/docs/02-app/02-api-reference/08-legacy-apis/unstable_noStore.mdx similarity index 100% rename from docs/02-app/02-api-reference/04-functions/unstable_noStore.mdx rename to docs/02-app/02-api-reference/08-legacy-apis/unstable_noStore.mdx