turbopack

Summary: The `turbopack` option lets you customize Turbopack to transform different files and change how modules are resolved.

Overview

The `turbopack` option lets you customize [Turbopack](/docs/app/api-reference/turbopack) to transform different files and change how modules are resolved.

> **Good to know** : The `turbopack` option…

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  turbopack: {
    // ...
  },
}

export default nextConfig

Reference

Options

The following options are available for the `turbopack` configuration:

| Option | Description |
| --- | --- |
| `root` | Sets the application root directory. Should be an absolute path. |
| `rules`…

Supported loaders

The following loaders have been tested to work with Turbopack's webpack loader implementation, but many other webpack loaders should work as well even if not listed here:

-…

Missing Webpack loader features

Turbopack uses the [`loader-runner`](https://github.com/webpack/loader-runner) library to execute webpack loaders, which provides most of the standard loader API. However, some features are not…

Examples

Root directory

Turbopack uses the root directory to resolve modules. Files outside of the project root are not resolved.

The reason files are not resolved outside of the project root is to improve cache…

const path = require('path')
module.exports = {
  turbopack: {
    root: path.join(__dirname, '..'),
  },
}

Configuring webpack loaders

If you need loader support beyond what's built in, many webpack loaders already work with Turbopack. There are currently some limitations:

- Only a core subset of the webpack loader API is…

module.exports = {
  turbopack: {
    rules: {
      '*.svg': {
        loaders: ['@svgr/webpack'],
        as: '*.js',
      },
    },
  },
}

module.exports = {
  turbopack: {
    rules: {
      '*.svg': {
        loaders: [
          {
            loader: '@svgr/webpack',
            options: {
              icon: true,
            },…

Advanced webpack loader conditions

You can further restrict where a loader runs using the advanced `condition` syntax:

- Supported boolean operators are `{all: [...]}`, `{any: [...]}` and `{not: ...}`.
- Supported customizable…

module.exports = {
  turbopack: {
    rules: {
      // '*' will match all file paths, but we restrict where our
      // rule runs with a condition.
      '*': {
        condition: {
          all:…

module.exports = {
  turbopack: {
    rules: {
      '*.svg': [
        {
          condition: 'browser',
          loaders: ['@svgr/webpack'],
          as: '*.js',
        },
        {…

Module types

You can set the module type directly without using a loader. This is useful for changing how files are processed, similar to webpack's [`type`](https://webpack.js.org/configuration/module/#ruletype)…

module.exports = {
  turbopack: {
    rules: {
      '*.svg': {
        type: 'asset',
      },
    },
  },
}

import svgUrl from './icon.svg'

export default function Page() {
  return <img src={svgUrl} alt="Icon" />
}

Inline loader configuration with import attributes

You can apply a Turbopack loader to an individual import using the `with` clause (import attributes). This is specified per-import rather than globally via `turbopack.rules`.

This is useful when you…

// Apply a raw loader to import a .txt file as a JavaScript module
import rawText from '../data.txt' with { turbopackLoader: 'raw-loader', turbopackAs: '*.js' }

export default function Page() {…

import value from '../data.js' with { turbopackLoader: 'string-replace-loader', turbopackLoaderOptions: '{"search":"PLACEHOLDER","replace":"replaced value"}' }

Resolving aliases

Turbopack can be configured to modify module resolution through aliases, similar to webpack's [`resolve.alias`](https://webpack.js.org/configuration/resolve/#resolvealias) configuration.

To…

module.exports = {
  turbopack: {
    resolveAlias: {
      underscore: 'lodash',
      mocha: { browser: 'mocha/browser-entry.js' },
    },
  },
}

Resolving custom extensions

Turbopack can be configured to resolve modules with custom extensions, similar to webpack's [`resolve.extensions`](https://webpack.js.org/configuration/resolve/#resolveextensions) configuration.

To…

module.exports = {
  turbopack: {
    resolveExtensions: ['.mdx', '.tsx', '.ts', '.jsx', '.js', '.mjs', '.json'],
  },
}

Debug IDs

Turbopack can be configured to generate [debug IDs](https://github.com/tc39/ecma426/blob/main/proposals/debug-id.md) in JavaScript bundles and source maps.

To configure debug IDs, use the `debugIds`…

module.exports = {
  turbopack: {
    debugIds: true,
  },
}

Version History

| Version | Changes |
| --- | --- |
| `16.2.0` | `turbopackLoader` import attributes were added. |
| `16.2.0` | `turbopack.rules.*.type` was added. |
| `16.2.0` |…

rules

List of supported webpack loaders to apply when running with Turbopack.

resolveAlias

Map aliased imports to modules to load in their place.

resolveExtensions

List of extensions to resolve when importing files.

debugIds

Enable generation of debug IDs in JavaScript bundles and source maps.


turbopackChunking

Summary: Configuration options for Turbopack's production JavaScript chunker in next.config.js, including size thresholds, component chunks, and heuristics for merging chunks.

Overview

This feature is currently experimental and subject to change, it's not recommended for production. Try it out and share your feedback on…

import type { NextConfig } from 'next'

const nextConfig = {
  experimental: {
    turbopackChunking: {
      minChunkSize: 50000,
      maxChunkCountPerGroup: 40,
      maxMergeChunkSize: 200000,…

Size Thresholds

The following options control how aggressively Turbopack merges chunks and how large a chunk is allowed to grow. Sizes are in bytes of uncompressed, unminified code (roughly 5x the size of the…

Component Chunks

Producing component chunks is an experimental feature that aims to give you the initial page load benefits of merged chunks without sacrificing reusability. This feature lets the runtime dynamically…

Heuristics

These change the assumptions the chunker makes when weighing whether merging two chunks is worth it.

- **`firstPageLoadPriority`** (a number between `0` and `1`): how heavily to weight the benefit…

minChunkSize

Turbopack will avoid creating more than one chunk smaller than this size by merging small chunks into larger ones. Raising this number will produce fewer, larger chunks. Meanwhile, lowering it will…

maxChunkCountPerGroup

Turbopack will not emit more than this many chunks per chunk group (eg. a route or a dynamic import). Lowering this number will lead to more aggressive merging and less network requests per-page.…

maxMergeChunkSize

Turbopack never merges a chunk larger than this size with other chunks. This keeps the code in large chunks from being duplicated across multiple large output chunks.

generateComponentChunks

When enabled, each merged production chunk also emits its constituent component chunks alongside it, so the browser runtime can fetch individual component chunks.

minComponentChunkSize

Component chunks smaller than this size are folded into a single component instead of being emitted on their own, to avoid producing many tiny chunks.

firstPageLoadPriority

How heavily to weight the benefit of merging chunks for a single page load. Higher values merge more eagerly. If you don't have a better value, your site's bounce rate is a good approximation.

priorityRoutes

Routes that are often the first page a visitor lands on (e.g. the homepage). Their client-side bundles are merged more eagerly to reduce the single-route request cost, at the cost of extra requests…

priorityBoost

A multiplier on the single-request probability of priorityRoutes routes. Higher values merge those routes' bundles more aggressively.

requestCost

The estimated cost of an additional request, in bytes of uncompressed, unminified code. Larger values bias toward fewer, larger chunks and fewer requests overall.


Turbopack FileSystem Caching

Summary: This page describes the Turbopack FileSystem Cache configuration options in Next.js, which enable caching of Turbopack's work across dev and build commands to speed up subsequent runs.

Usage

Turbopack FileSystem Cache enables Turbopack to reduce work across `next dev` or `next build` commands. When enabled, Turbopack will save and restore data under the `.next` directory between runs,…

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  experimental: {
    turbopackFileSystemCacheForDev: true,
    turbopackFileSystemCacheForBuild: true,
  },
}

export…

Options

- **`turbopackFileSystemCacheForDev`**  (default: `true`): caches Turbopack's work for `next dev` in `.next/dev/cache/turbopack`. Restarting the dev server reuses the previous compilation.

-…

Build environments

The build cache lives in `.next/cache`. Builds only get faster when that directory is restored before each build.

- **Self-hosted builds** : reuse the same working directory between builds.…

Version History

| Version | Changes |
| --- | --- |
| `v16.3.0` | FileSystem caching is enabled by default for builds |
| `v16.1.0` | FileSystem caching is enabled by default for development |
| `v16.0.0` | Beta…

turbopackFileSystemCacheForBuild

caches Turbopack's work for `next build` in `.next/cache/turbopack`. Subsequent builds start warm. See Build environments.


turbopack.ignoreIssue

Summary: The `turbopack.ignoreIssue` option allows you to filter out specific Turbopack errors and warnings so they do not appear in the CLI output or the error overlay. This is useful for suppressing known…

turbopack.ignoreIssue

Usage

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  turbopack: {
    ignoreIssue: [
      {
        path: '**/vendor/**',
      },
    ],
  },
}

export default nextConfig

Options

Each rule in the `ignoreIssue` array is an object with the following fields:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | `string \| RegExp` | Yes | Matches against…

path

A **glob pattern** (when a string) or **regular expression** that matches against the file path where the issue originated.

module.exports = {
  turbopack: {
    ignoreIssue: [
      // Glob pattern: suppress issues from any file under vendor/
      { path: '**/vendor/**' },
      // RegExp: suppress issues from files…

title

An **exact string match** (when a string) or **regular expression** that matches against the issue title.

module.exports = {
  turbopack: {
    ignoreIssue: [
      {
        path: '**/src/**',
        title: 'Module not found',
      },
    ],
  },
}

description

An **exact string match** (when a string) or **regular expression** that matches against the issue description.

module.exports = {
  turbopack: {
    ignoreIssue: [
      {
        path: '**/src/**',
        description: /Cannot find module 'optional-dep'/,
      },
    ],
  },
}

Examples

Suppressing warnings for optional dependencies

If your code uses `try/catch` around an optional `require()` call, Turbopack may report a "Module not found" warning. You can suppress it:

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  turbopack: {
    ignoreIssue: [
      {
        path: '**/lib/optional-feature/**',
        title: 'Module not found',…

Combining multiple rules

You can specify multiple rules to suppress different issues:

module.exports = {
  turbopack: {
    ignoreIssue: [
      { path: '**/vendor/**' },
      { path: '**/legacy/**', title: 'Module not found' },
      { path: /generated\//, description: /expected…

Version History

| Version | Changes |
| --- | --- |
| `v16.2.0` | `turbopack.ignoreIssue` introduced. |

Next Steps

Learn more about Turbopack configuration.

- [turbopack: Configure Next.js with Turbopack-specific options](/docs/app/api-reference/config/next-config-js/turbopack)
- [Turbopack: Turbopack is an…

path

Matches against the file path of the issue. A glob pattern (when a string) or a regular expression.

title

Matches against the issue title. An exact string match (when a string) or a regular expression.

description

Matches against the issue description. An exact string match (when a string) or a regular expression.


turbopackLocalPostcssConfig

Summary: This page documents the `turbopackLocalPostcssConfig` option in Next.js configuration, which changes how Turbopack resolves `postcss.config.js` files, allowing per-directory configs to take…

Overview

The `turbopackLocalPostcssConfig` option changes how Turbopack resolves `postcss.config.js` files. When enabled, Turbopack searches for the config starting from the CSS file's own directory first,…

Usage

To enable the option, set `experimental.turbopackLocalPostcssConfig` to `true` in your `next.config.ts` file.

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  experimental: {
    turbopackLocalPostcssConfig: true,
  },
}

export default nextConfig

Behavior

The table below shows the config resolution order for each setting:

- `false` (default): Project root → CSS file's directory
- `true`: CSS file's directory → project root

With the default behavior,…

Example

This is useful for projects that need different PostCSS transforms in different directories, such as a monorepo with multiple apps or design system packages. The following directory structure…

my-app/
├── postcss.config.js          ← fallback (applied if no local config is found)
├── app/
│   └── page.module.css        ← uses root config
└── packages/
    └── ui/
        ├──…

Version History

The following table lists the version history for this feature:

- `v16.3.0`: `turbopackLocalPostcssConfig` introduced.


next.config.js: turbopackMemoryEviction | Next.js

Summary: Explains the experimental `turbopackMemoryEviction` option in Next.js, which controls whether Turbopack reclaims memory when the FileSystem cache is enabled, including its three possible settings and…

Usage

`turbopackMemoryEviction` controls whether Turbopack reclaims memory while the persistent (FileSystem) cache is enabled. After Turbopack writes a snapshot of its cache to disk, it can 'evict' the…

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  experimental: {
    turbopackMemoryEviction: 'auto',
  },
}

export default nextConfig

Version Changes

| Version | Changes |
| --- | --- |
| `v16.3.0` | `turbopackMemoryEviction` released as experimental. |

turbopackMemoryEviction

Controls whether Turbopack reclaims memory while the persistent (FileSystem) cache is enabled. Accepts `false`, `'auto'`, or `'full'`.


turbopackRustReactCompiler

Summary: The `experimental.turbopackRustReactCompiler` option enables the native Rust version of the React Compiler, running it directly inside Turbopack as native code instead of through Node.js with the…

turbopackRustReactCompiler

This feature is currently experimental and subject to change, it's not recommended for production. Try it out and share your feedback on GitHub.

The `experimental.turbopackRustReactCompiler` option…

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  // Enable the React Compiler
  reactCompiler: true,
  experimental: {
    // Use the Rust port instead of the Babel…

Good to know

- This option requires `reactCompiler` to be enabled. It selects which implementation runs, but does not turn the compiler on by itself.
- This option is only supported with Turbopack. Using it with…

Version History

| Version | Changes |
| --- | --- |
| `v16.3.0` | Introduced the experimental `turbopackRustReactCompiler` option for the native Rust React Compiler. |


typedRoutes

Summary: Configuration option for Next.js that enables statically typed links. Requires TypeScript in the project.

typedRoutes

Note: This option has been marked as stable, so you should use `typedRoutes` instead of `experimental.typedRoutes`.

Support for statically typed links. This feature requires using TypeScript in your…

/** @type {import('next').NextConfig} */
const nextConfig = {
  typedRoutes: true,
}

module.exports = nextConfig


typescript

Summary: Configure TypeScript behavior with the `typescript` option in `next.config.js`.

typescript

Configure TypeScript behavior with the `typescript` option in `next.config.js`:

module.exports = {
  typescript: {
    ignoreBuildErrors: false,
    tsconfigPath: 'tsconfig.json',
  },
}

Options

ignoreBuildErrors

Next.js fails your **production build** (`next build`) when TypeScript errors are present in your project.

If you'd like Next.js to dangerously produce production code even when your application has…

module.exports = {
  typescript: {
    // !! WARN !!
    // Dangerously allow production builds to successfully complete even if
    // your project has type errors.
    // !! WARN !!…

tsconfigPath

Use a different TypeScript configuration file for builds or tooling:

See the [TypeScript configuration](/docs/app/api-reference/config/typescript#custom-tsconfig-path) page for more details.

module.exports = {
  typescript: {
    tsconfigPath: 'tsconfig.build.json',
  },
}

ignoreBuildErrors

Allow production builds to complete even with TypeScript errors.

tsconfigPath

Path to a custom `tsconfig.json` file.


next.config.js: urlImports | Next.js

Summary: Documentation for the experimental urlImports feature in Next.js, which allows importing modules directly from external URLs, with configuration, security model, lockfile behavior, and examples.

urlImports

URL imports are an experimental feature that allows you to import modules directly from external servers (instead of from the local disk).

> **Warning** : Only use domains that you trust to download…

module.exports = {
  experimental: {
    urlImports: ['https://example.com/assets/', 'https://cdn.skypack.dev'],
  },
}

import { a, b, c } from 'https://example.com/assets/some/module.js'

Security Model

This feature is being designed with **security as the top priority** . To start, we added an experimental flag forcing you to explicitly allow the domains you accept URL imports from. We're working…

Lockfile

When using URL imports, Next.js will create a `next.lock` directory containing a lockfile and fetched assets. This directory **must be committed to Git** , not ignored by `.gitignore`.

- When…

Examples

###### Skypack

###### Static Image Imports

###### URLs in CSS

###### Asset Imports

import confetti from 'https://cdn.skypack.dev/canvas-confetti'
import { useEffect } from 'react'

export default () => {
  useEffect(() => {
    confetti()
  })
  return
Hello

}

import Image from 'next/image'
import logo from 'https://example.com/assets/logo.png'

export default () => (
  <div>
    <Image src={logo} placeholder="blur" />
  </div>
)

.className {
  background: url('https://example.com/assets/hero.jpg');
}

const logo = new URL('https://example.com/assets/file.txt', import.meta.url)

console.log(logo.pathname)

// prints "/_next/static/media/file.a9727b5d.txt"


useLightningcss

Summary: Experimental support for using Lightning CSS with webpack, and configuration options for controlling CSS feature transpilation.

useLightningcss

This feature is currently experimental and subject to change, it's not recommended for production. Try it out and share your feedback on GitHub.

Experimental support for using Lightning CSS with…

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  experimental: {
    useLightningcss: false, // default, ignored on Turbopack
  },
}

export default nextConfig

lightningCssFeatures

By default, Lightning CSS decides which CSS features to transpile based on your browserslist targets. The `lightningCssFeatures` option lets you override this by forcing specific features to always…

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  experimental: {
    useLightningcss: true,
    lightningCssFeatures: {
      // Always transpile these features, even if…

Options

| Option | Type | Description |
| --- | --- | --- |
| `include` | `string[]` | Features to always transpile, regardless of browser targets. |
| `exclude` | `string[]` | Features to never transpile,…

Available features

Individual features:

| Feature name | Description |
| --- | --- |
| `nesting` | CSS Nesting |
| `not-selector-list` | `:not` with multiple selectors |
| `dir-selector` | `:dir()` selector |
|…

Version History

| Version | Changes |
| --- | --- |
| `16.2.0` | `lightningCssFeatures` added. |
| `15.1.0` | Support for `useSwcCss` was removed from Turbopack. |
| `14.2.0` | Turbopack's default CSS processor was…

useLightningcss

Enables Lightning CSS for webpack. Defaults to false. Ignored on Turbopack.

lightningCssFeatures.exclude

Features to never transpile, even when browser targets would require them.


next.config.js: useOffline | Next.js

Summary: This page documents the experimental `useOffline` configuration option in Next.js, which enables offline connectivity detection, automatic retry of failed navigation, prefetch, and Server Action…

useOffline

This feature is currently experimental and subject to change, it's not recommended for production. Try it out and share your feedback on GitHub.

The `useOffline` configuration option enables offline…

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  experimental: {
    useOffline: true,
  },
}

export default nextConfig

How retry works

The offline state is entered through one of two paths:

- **Browser event.** Next.js registers a `window.addEventListener('offline', ...)` listener. When the OS reports the network interface as down,…

The connectivity check

Each check issues a single `HEAD` request to the current page's URL with the RSC header set, the same endpoint navigations use. The request is aborted after 200 ms.

Two outcomes count as…

Backoff

Delays between checks are stepped, not exponential, and capped at 3 seconds:

| Attempt | Delay before next check |
| --- | --- |
| 1 | 500 ms |
| 2 | 1 s |
| 3 | 2 s |
| 4 and after | 3 s |

The…

Giving up

The polling loop never gives up on its own. It continues at the 3-second cap until a check succeeds or the page unloads. A device that goes offline for hours and then regains connectivity will have…

Retry of framework requests

While the offline state is active, any navigation, prefetch, or Server Action waits for the next connectivity check to succeed, whether it was newly issued or already in flight when the connection…

Traffic at reconnection

A single client does not produce a runaway burst of traffic against its origin:

- While the client is offline, a failed `fetch()` rejects locally at the browser's network layer. The request never…

Version History

| Version | Changes |
| --- | --- |
| `v16.x.0` | `experimental.useOffline` configuration option introduced. |


next.config.js: useTypeScriptCli | Next.js

Summary: Documents the experimental `experimental.useTypeScriptCli` configuration option, which controls whether `next build` uses the project-local `tsc` CLI or the TypeScript JavaScript compiler API for…

useTypeScriptCli

This feature is currently experimental and subject to change, it's not recommended for production. Try it out and share your feedback on [GitHub](https://github.com/vercel/next.js/issues).

By…

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  experimental: {
    useTypeScriptCli: false,
  },
}

export default nextConfig

Behavior

- Next.js continues to generate `next-env.d.ts` and route types and to apply its recommended `tsconfig` settings before running the checker.

- TypeScript diagnostics are printed directly from `tsc`.…

experimental.useTypeScriptCli

When true, `next build` uses the project-local `tsc` CLI command for type checking. When false, Next.js loads the TypeScript JavaScript compiler API instead. This is experimental; setting it to false…


webVitalsAttribution

Summary: Explains the experimental webVitalsAttribution option in next.config.js, which enables per-metric Web Vitals attribution to help pinpoint the source of Web Vitals issues.

webVitalsAttribution

This feature is currently experimental and subject to change, it's not recommended for production. Try it out and share your feedback on [GitHub](https://github.com/vercel/next.js/issues).

When…

module.exports = {
  experimental: {
    webVitalsAttribution: ['CLS', 'LCP'],
  },
}


Custom Webpack Config

Summary: Describes how to customize the webpack configuration in Next.js using the `webpack` option in `next.config.js`, including the properties available in the second argument and an example of extending…

Custom Webpack Config

**Good to know** : changes to webpack config are not covered by semver so proceed at your own risk

Before continuing to add custom webpack configuration to your application make sure Next.js doesn't…

module.exports = {
  webpack: (
    config,
    { buildId, dev, isServer, defaultLoaders, nextRuntime, webpack }
  ) => {
    // Important: return the modified config
    return config
  },
}

// Example config for adding a loader that depends on babel-loader
// This source was taken from the @next/mdx plugin source:
//…

nextRuntime

Notice that `isServer` is `true` when `nextRuntime` is `"edge"` or `"nodejs"`, `nextRuntime` `"edge"` is currently for proxy and Server Components in edge runtime only.

config

The webpack configuration object that should be modified and returned.

buildId

The build id, used as a unique identifier between builds.

dev

Indicates if the compilation will be done in development.

isServer

It's `true` for server-side compilation, and `false` for client-side compilation.

nextRuntime

The target runtime for server-side compilation; either `"edge"` or `"nodejs"`, it's `undefined` for client-side compilation.

defaultLoaders

Default loaders used internally by Next.js. Contains `babel`: `Object` - Default `babel-loader` configuration.

webpack

The webpack instance used by Next.js.


Configuration: TypeScript | Next.js

Summary: Extraction fallback content.

Configuration: TypeScript | Next.js

This page is also available as Markdown: request this page's URL with an `Accept: text/markdown` header.   For an index of  Next.js documentation , see  [/docs/llms.txt](/docs/llms.txt).Copy page

##### TypeScript

Last updated  August 3, 2026

Next.js comes with built-in TypeScript, automatically installing the necessary packages and configuring the proper settings when you create a new project with `create-next-app`.

To add TypeScript to an existing project, rename a file to `.ts` / `.tsx`. Run `next dev` and `next build` to automatically install the necessary dependencies and add a `tsconfig.json` file with the recommended config options.

> **Good to know** : If you already have a `jsconfig.json` file, copy the `paths` compiler option from the old `jsconfig.json` into the new `tsconfig.json` file, and delete the old `jsconfig.json` file.

##### Using TypeScript 7

[TypeScript 7](https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/) does not currently provide the JavaScript compiler API. To use TypeScript 7 during `next build`, install it in your project:

pnpmnpmyarnbunTerminal

Next.js uses the project-local `tsc` CLI by default, so no additional configuration is required. To use the JavaScript compiler API instead, set [`experimental.useTypeScriptCli`](/docs/app/api-reference/config/next-config-js/useTypeScriptCli) to `false`.

> **Good to know** :
>
>
>
>
>
>
> - CLI type checking prints the native `tsc` diagnostics. It does not apply Next.js-specific code frames or rewrite errors for routes, pages, layouts, or route handlers.
>
> - The CLI checks the complete project selected by your `tsconfig` file. This includes test files and `.next/dev/types` when they are included by that configuration. [`next build --debug-build-paths`](/docs/app/api-reference/cli/next#next-build-options) does not narrow the files that are type checked and produces a warning when used with this option.
>
> - [`typescript.tsconfigPath`](#custom-tsconfig-path) continues to select the configuration passed to `tsc`. [`typescript.ignoreBuildErrors`](#disabling-typescript-errors-in-production) skips the type-checking step, including the CLI checker.
>
> - `experimental.useTypeScriptCli` is experimental and its behavior may change.

##### IDE Plugin

Next.js includes a custom TypeScript plugin and type checker, which VSCode and other code editors can use for advanced type-checking and auto-completion.

You can enable the plugin in VS Code by:

- Opening the command palette (`Ctrl/⌘` + `Shift` + `P`)

- Searching for "TypeScript: Select TypeScript Version"

- Selecting "Use Workspace Version"

Now, when editing files, the custom plugin will be enabled. By default, the project-local `tsc` CLI is used when running `next build`. Set [`experimental.useTypeScriptCli`](#using-typescript-7) to `false` to use the custom type checker instead.

The TypeScript plugin can help with:

- Warning if invalid values for [segment config options](/docs/app/api-reference/file-conventions/route-segment-config) are passed.

- Showing available options and in-context documentation.

- Ensuring the `'use client'` directive is used correctly.

- Ensuring client hooks (like `useState`) are only used in Client Components.

> **🎥 Watch:**  Learn about the built-in TypeScript plugin → [YouTube (3 minutes)](https://www.youtube.com/watch?v=pqMqn9fKEf8)

##### End-to-End Type Safety

The Next.js App Router has  **enhanced type safety** . This includes:

- **No serialization of data between fetching function and page** : You can `fetch` directly in components, layouts, and pages on the server. This data  *does not*  need to be serialized (converted to a string) to be passed to the client side for consumption in React. Instead, since `app` uses Server Components by default, we can use values like `Date`, `Map`, `Set`, and more without any extra steps. Previously, you needed to manually type the boundary between server and client with Next.js-specific types.

- **Streamlined data flow between components** : With the removal of `_app` in favor of root layouts, it is now easier to visualize the data flow between components and pages. Previously, data flowing between individual `pages` and `_app` were difficult to type and could introduce confusing bugs. With [colocated data fetching](/docs/app/getting-started/fetching-data) in the App Router, this is no longer an issue.

[Data Fetching in Next.js](/docs/app/getting-started/fetching-data) now provides as close to end-to-end type safety as possible without being prescriptive about your database or content provider selection.

We're able to type the response data as you would expect with normal TypeScript. For example:

app/page.tsxTypeScriptJavaScriptTypeScript

For  *complete*  end-to-end type safety, this also requires your database or content provider to support TypeScript. This could be through using an [ORM](https://en.wikipedia.org/wiki/Object%E2%80%93relational_mapping) or type-safe query builder.

##### Route-Aware Type Helpers

Next.js generates global helpers for App Router route types. These are available without imports and are generated during `next dev`, `next build`, or via [`next typegen`](/docs/app/api-reference/cli/next#next-typegen-options):

- [`PageProps`](/docs/app/api-reference/file-conventions/page#page-props-helper)

- [`LayoutProps`](/docs/app/api-reference/file-conventions/layout#layout-props-helper)

- [`RouteContext`](/docs/app/api-reference/file-conventions/route#route-context-helper)

##### `next-env.d.ts`

Next.js generates a `next-env.d.ts` file in your project root. This file references Next.js type definitions, allowing TypeScript to recognize non-code imports (images, stylesheets, etc.) and Next.js-specific types.

Running `next dev`, `next build`, or [`next typegen`](/docs/app/api-reference/cli/next#next-typegen-options) regenerates this file.

> **Good to know** :
>
>
>
>
>
>
> - `next-env.d.ts` is managed by Next.js. Its contents are an implementation detail and may change over time. Add it to `.gitignore`. If your project already tracks the file, remove it from Git. Do not edit this file manually.
>
> - The file must be in your `tsconfig.json` `include` array (`create-next-app` does this automatically).

##### Examples

###### Type Checking Next.js Configuration Files

You can use TypeScript and import types in your Next.js configuration by using `next.config.ts`.

next.config.ts

Module resolution in `next.config.ts` is currently limited to CommonJS. However, ECMAScript Modules (ESM) syntax is available when [using Node.js native TypeScript resolver](#using-nodejs-native-typescript-resolver-for-nextconfigts) for Node.js v22.10.0 and higher.

When using the `next.config.js` file, you can add some type checking in your IDE using JSDoc as below:

next.config.js

###### Using Node.js Native TypeScript Resolver for `next.config.ts`

> **Note** : Available on Node.js v22.10.0+ and only when the feature is enabled. Next.js does not enable it.

Next.js detects the [Node.js native TypeScript resolver](https://nodejs.org/api/typescript.html) via [`process.features.typescript`](https://nodejs.org/api/process.html#processfeaturestypescript), added in  **v22.10.0** . When present, `next.config.ts` can use native ESM, including top‑level `await` and dynamic `import()`. This mechanism inherits the capabilities and limitations of Node's resolver.

In Node.js versions  **v22.18.0+** , `process.features.typescript` is enabled by default. For versions between  **v22.10.0**  and  **22.17.x** , opt in with `NODE_OPTIONS=--experimental-transform-types`:

Terminal

###### For CommonJS Projects (Default)

Although `next.config.ts` supports native ESM syntax in CommonJS projects, Node.js will still assume `next.config.ts` is a CommonJS file by default, resulting in Node.js reparsing the file as ESM when module syntax is detected. Therefore, we recommend using the `next.config.mts` file for CommonJS projects to explicitly indicate it's an ESM module:

next.config.mts

###### For ESM Projects

When `"type"` is set to `"module"` in `package.json`, your project uses ESM. Learn more about this setting [in the Node.js docs](https://nodejs.org/api/packages.html#type). In this case, you can write `next.config.ts` directly with ESM syntax.

> **Good to know** : When using `"type": "module"` in your `package.json`, all `.js` and `.ts` files in your project are treated as ESM modules by default. You may need to rename files with CommonJS syntax to `.cjs` or `.cts` extensions if needed.

###### Statically Typed Links

Next.js can statically type links to prevent typos and other errors when using `next/link`, improving type safety when navigating between pages.

Works in both the Pages and App Router for the `href` prop in `next/link`. In the App Router, it also types `next/navigation` methods like `push`, `replace`, and `prefetch`. It does not type `next/router` methods in Pages Router.

Literal `href` strings are validated, while non-literal `href`s may require a cast with `as Route`.

To opt-into this feature, `typedRoutes` needs to be enabled and the project needs to be using TypeScript.

next.config.ts

Next.js will generate a link definition in `.next/types` that contains information about all existing routes in your application, which TypeScript can then use to provide feedback in your editor about invalid links.

> **Good to know** : If you set up your project without `create-next-app`, ensure the generated Next.js types are included by adding `.next/types/**/*.ts` to the `include` array in your `tsconfig.json`:

tsconfig.json

Currently, support includes any string literal, including dynamic segments. For non-literal strings, you need to manually cast with `as Route`. The example below shows both `next/link` and `next/navigation` usage:

app/example-client.tsx

The same applies for redirecting routes defined by proxy:

proxy.ts
app/some/page.tsx

To accept `href` in a custom component wrapping `next/link`, use a generic:

You can also type a simple data structure and iterate to render links:

components/nav-items.ts

Then, map over the items to render `Link`s:

components/nav.tsx

> **How does it work?**
>
>
>
>
> When running, `next typegen`, `next dev` or `next build`, Next.js generates a hidden `.d.ts` file inside `.next` that contains information about all existing routes in your application (all valid routes as the `href` type of `Link`). This `.d.ts` file is included in `tsconfig.json` and the TypeScript compiler will check that `.d.ts` and provide feedback in your editor about invalid links.

###### Type IntelliSense for Environment Variables

During development, Next.js generates a `.d.ts` file in `.next/types` that contains information about the loaded environment variables for your editor's IntelliSense. If the same environment variable key is defined in multiple files, it is deduplicated according to the [Environment Variable Load Order](/docs/app/guides/environment-variables#environment-variable-load-order).

To opt-into this feature, `experimental.typedEnv` needs to be enabled and the project needs to be using TypeScript.

next.config.ts

> **Good to know** : Types are generated based on the environment variables loaded at development runtime, which excludes variables from `.env.production*` files by default. To include production-specific variables, run `next dev` with `NODE_ENV=production`.

###### With Async Server Components

To use an `async` Server Component with TypeScript, ensure you are using TypeScript `5.1.3` or higher and `@types/react` `18.2.8` or higher.

If you are using an older version of TypeScript, you may see a `'Promise<Element>' is not a valid JSX element` type error. Updating to the latest version of TypeScript and `@types/react` should resolve this issue.

###### Incremental type checking

Since `v10.2.1` Next.js supports [incremental type checking](https://www.typescriptlang.org/tsconfig#incremental) when enabled in your `tsconfig.json`, this can help speed up type checking in larger applications.

###### Custom `tsconfig` path

In some cases, you might want to use a different TypeScript configuration for builds or tooling. To do that, set `typescript.tsconfigPath` in `next.config.ts` to point Next.js to another `tsconfig` file.

next.config.ts

For example, switch to a different config for production builds:

next.config.ts
Why you might use a separate `tsconfig` for builds

You might need to relax checks in scenarios like monorepos, where the build also validates shared dependencies that don't match your project's standards, or when loosening checks in CI to continue delivering while migrating locally to stricter TypeScript settings (and still wanting your IDE to highlight misuse).

For example, if your project uses `useUnknownInCatchVariables` but some monorepo dependencies still assume `any`:

tsconfig.build.json

This keeps your editor strict via `tsconfig.json` while allowing the production build to use relaxed settings.

> **Good to know** :
>
>
>
>
>
>
> - IDEs typically read `tsconfig.json` for diagnostics and IntelliSense, so you can still see IDE warnings while production builds use the alternate config. Mirror critical options if you want parity in the editor.
>
> - In development, only `tsconfig.json` is watched for changes. If you edit a different file name via `typescript.tsconfigPath`, restart the dev server to apply changes.
>
> - The configured file is used in `next dev`, `next build`, and `next typegen`.

###### Disabling TypeScript errors in production

Next.js fails your  **production build**  (`next build`) when TypeScript errors are present in your project.

If you'd like Next.js to dangerously produce production code even when your application has errors, you can disable the built-in type checking step.

If disabled, be sure you are running type checks as part of your build or deploy process, otherwise this can be very dangerous.

Open `next.config.ts` and enable the `ignoreBuildErrors` option in the [`typescript`](/docs/app/api-reference/config/next-config-js/typescript) config:

next.config.ts

> **Good to know** : You can run `tsc --noEmit` to check for TypeScript errors yourself before building. This is useful for CI/CD pipelines where you'd like to check for TypeScript errors before deploying.

###### Custom type declarations

When you need to declare custom types, you might be tempted to modify `next-env.d.ts`. However, this file is automatically generated, so any changes you make will be overwritten. Instead, you should create a new file, let's call it `new-types.d.ts`, and reference it in your `tsconfig.json`:

tsconfig.json

##### Version Changes

| Version | Changes |
| --- | --- |

| `v15.0.0` | [`next.config.ts`](#type-checking-nextjs-configuration-files) support added for TypeScript projects. |
| `v13.2.0` | Statically typed links are available in beta. |
| `v12.0.0` | [SWC](/docs/architecture/nextjs-compiler) is now used by default to compile TypeScript and TSX for faster builds. |
| `v10.2.1` | [Incremental type checking](https://www.typescriptlang.org/tsconfig#incremental) support added when enabled in your `tsconfig.json`. |

Was this helpful?

supported.Send

async function getData() {
  const res = await fetch('https://api.example.com/...')
  // The return value is *not* serialized
  // You can return Date, Map, Set, etc.
  return res.json()
}

export default async function Page() {
  const name = await getData()

  return '...'
}

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  /* config options here */
}

export default nextConfig

// @ts-check

/** @type {import('next').NextConfig} */
const nextConfig = {
  /* config options here */
}

module.exports = nextConfig

import type { NextConfig } from 'next'

// Top-level await and dynamic import are supported
const flags = await import('./flags.js').then((m) => m.default ?? m)

const nextConfig: NextConfig = {
  /* config options here */
  typedRoutes: Boolean(flags?.typedRoutes),
}

export default nextConfig

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  typedRoutes: true,
}

export default nextConfig

'use client'

import type { Route } from 'next'
import Link from 'next/link'
import { useRouter } from 'next/navigation'

export default function Example() {
  const router = useRouter()
  const slug = 'nextjs'

  return (
    <>
      {/* Link: literal and dynamic */}
      <Link href="/about" />
      <Link href={`/blog/${slug}`} />
      <Link href={('/blog/' + slug) as Route} />
      {/* TypeScript error if href is not a valid route */}
      <Link href="/aboot" />

      {/* Router: literal and dynamic strings are validated */}
      <button onClick={() => router.push('/about')}>Push About</button>
      <button onClick={() => router.replace(`/blog/${slug}`)}>
        Replace Blog
      </button>
      <button onClick={() => router.prefetch('/contact')}>
        Prefetch Contact
      </button>

      {/* For non-literal strings, cast to Route */}
      <button onClick={() => router.push(('/blog/' + slug) as Route)}>
        Push Non-literal Blog
      </button>
    </>
  )
}

import { NextRequest, NextResponse } from 'next/server'

export function proxy(request: NextRequest) {
  if (request.nextUrl.pathname === '/proxy-redirect') {
    return NextResponse.redirect(new URL('/', request.url))
  }

  return NextResponse.next()
}

import type { Route } from 'next'

export default function Page() {
  return <Link href={'/proxy-redirect' as Route}>Link Text</Link>
}

import type { Route } from 'next'
import Link from 'next/link'

function Card<T extends string>({ href }: { href: Route<T> | URL }) {
  return (
    <Link href={href}>

My Card

    </Link>
  )
}

import type { Route } from 'next'

type NavItem<T extends string = string> = {
  href: T
  label: string
}

export const navItems: NavItem<Route>[] = [
  { href: '/', label: 'Home' },
  { href: '/about', label: 'About' },
  { href: '/blog', label: 'Blog' },
]

import Link from 'next/link'
import { navItems } from './nav-items'

export function Nav() {
  return (
    <nav>
      {navItems.map((item) => (
        <Link key={item.href} href={item.href}>
          {item.label}
        </Link>
      ))}
    </nav>
  )
}

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  experimental: {
    typedEnv: true,
  },
}

export default nextConfig

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  typescript: {
    tsconfigPath: 'tsconfig.build.json',
  },
}

export default nextConfig

import type { NextConfig } from 'next'

const isProd = process.env.NODE_ENV === 'production'

const nextConfig: NextConfig = {
  typescript: {
    tsconfigPath: isProd ? 'tsconfig.build.json' : 'tsconfig.json',
  },
}

export default nextConfig

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  typescript: {
    // !! WARN !!
    // Dangerously allow production builds to successfully complete even if
    // your project has type errors.
    // !! WARN !!
    ignoreBuildErrors: true,
  },
}

export default nextConfig

{
  "compilerOptions": {
    "skipLibCheck": true
    //...truncated...
  },
  "include": [
    "new-types.d.ts",
    "next-env.d.ts",
    ".next/types/**/*.ts",
    "**/*.ts",
    "**/*.tsx"
  ],
  "exclude": ["node_modules"]
}


Directives

Summary: This page provides an index of Next.js directives, including use cache, use client, and use server, with links to their detailed documentation.

Directives

The following directives are available:

- [use cache](/docs/app/api-reference/directives/use-cache): Learn how to use the "use cache" directive to cache data in your Next.js application.
- [use…


Directives: use cache | Next.js

Summary: Extraction fallback content.

Directives: use cache | Next.js

This page is also available as Markdown: request this page's URL with an `Accept: text/markdown` header.   For an index of  Next.js documentation , see  [/docs/llms.txt](/docs/llms.txt).Copy page

##### use cache

Last updated  July 22, 2026

The `use cache` directive allows you to mark a route, React component, or a function as cacheable. It can be used at the top of a file to indicate that all exports in the file should be cached, or inline at the top of a function or component to cache the return value. Functions and components that use `use cache` must be async.

> **Good to know:**
>
>
>
>
>
>
> - To use cookies or headers, read them outside cached scopes and pass values as arguments. This is the preferred pattern.
>
> - If the in-memory cache isn't sufficient for runtime data, [`'use cache: remote'`](/docs/app/api-reference/directives/use-cache-remote) allows platforms to provide a dedicated cache handler, though it requires a network roundtrip to check the cache and typically incurs platform fees.
>
> - For compliance requirements or when you can't refactor to pass runtime data as arguments to a `use cache` scope, see [`'use cache: private'`](/docs/app/api-reference/directives/use-cache-private).

##### Usage

`use cache` is a Cache Components feature. To enable it, add the [`cacheComponents`](/docs/app/api-reference/config/next-config-js/cacheComponents) option to your `next.config.ts` file:

next.config.tsTypeScriptJavaScriptTypeScript

Then, add `use cache` at the file, component, or function level. All functions and components using `use cache` must be async. When used at file level, every exported function becomes a cached function and must also be async:

##### How `use cache` works

###### Cache keys

A cache entry's key is generated using a serialized version of its inputs, which includes:

- **Build ID**  - Unique per build, changing this invalidates all cache entries. If [`deploymentId`](/docs/app/api-reference/config/next-config-js/deploymentId) is configured, it overrides the build ID for cache key purposes.

- **Function ID**  - A secure hash of the function's location and signature in the codebase

- **Serializable arguments**  - Props (for components) or function arguments

- **HMR refresh hash**  (development only) - Invalidates cache on hot module replacement

When a cached function references variables from outer scopes, those variables are automatically captured and bound as arguments, making them part of the cache key.

lib/data.ts

In the snippet above, `userId` is captured from the outer scope and `filter` is passed as an argument, so both become part of the `getData` function's cache key. This means different user and filter combinations will have separate cache entries.

> **Good to know:**  When a cached function reads [root parameters](/docs/app/api-reference/functions/next-root-params), only the ones it actually reads become part of its cache key.

##### Serialization

Arguments to cached functions and their return values must be serializable.

For a complete reference, see:

- [Serializable arguments](https://react.dev/reference/rsc/use-server#serializable-parameters-and-return-values) - Uses  **React Server Components**  serialization

- [Serializable return types](https://react.dev/reference/rsc/use-client#serializable-types) - Uses  **React Client Components**  serialization

> **Good to know:**  Arguments and return values use different serialization systems. Server Component serialization (for arguments) is more restrictive than Client Component serialization (for return values). This means you can return JSX elements but cannot accept them as arguments unless using pass-through patterns.

###### Supported types

 **Arguments:**

- Primitives: `string`, `number`, `boolean`, `null`, `undefined`

- Plain objects: `{ key: value }`

- Arrays: `[1, 2, 3]`

- Dates, Maps, Sets, TypedArrays, ArrayBuffers

- React elements (as pass-through only)

 **Return values:**

- Same as arguments, plus JSX elements

###### Unsupported types

- Class instances

- Functions (except as pass-through)

- Symbols, WeakMaps, WeakSets

- URL instances

app/components/user-card.tsx

###### Pass-through (non-serializable arguments)

You can accept non-serializable values  **as long as you don't introspect them** . This enables composition patterns with `children` and Server Actions:

app/components/cached-wrapper.tsx

You can also pass Server Actions through cached components:

app/components/cached-form.tsx

##### Constraints

Cached functions execute in an isolated environment. The following constraints ensure cache behavior remains predictable and secure.

###### Request-time APIs

Cached functions and components  **cannot**  access runtime APIs like `cookies()`, `headers()`, or `searchParams`, and the restriction follows the call stack: a helper the cached function calls that reads one of these fails the same way, with the [`next-request-in-use-cache`](/docs/messages/next-request-in-use-cache) error. On a dynamically rendered route this surfaces when the route runs, so it can pass `next build` and fail under `next start`. Read these values outside the cached scope and pass them as arguments.

###### Runtime caching considerations

While `use cache` is designed primarily to include uncached data in the static shell, it can also cache data at runtime using in-memory LRU (Least Recently Used) storage.

With the default in-memory handler, runtime cache behavior depends on your hosting environment:

| Environment | Runtime Caching Behavior |
| --- | --- |

| **Serverless** | Cache entries typically don't persist across requests (each request can be a different instance), or during revalidation. Build-time caching works normally. |
| **Self-hosted** | Cache entries persist across requests. Control cache size with [`cacheMaxMemorySize`](/docs/app/api-reference/config/next-config-js/incrementalCacheHandlerPath). |

For example, in a serverless environment, a cached function shared by two pages executes on each static shell revalidation, whereas in self-hosted or environments with persistent memory, the cached output is reused if it's still fresh.

If the default in-memory cache isn't enough, consider  **[`use cache: remote`](/docs/app/api-reference/directives/use-cache-remote)**  which allows platforms to provide a dedicated cache handler (like Redis or KV database). This helps reduce hits against data sources not scaled to your total traffic, though it comes with costs (storage, network latency, platform fees).

With the default in-memory handler, serverless instances are ephemeral, so entries may not be reused between requests, unlike with `use cache: remote`. Neither caching directive carries over to a new deploy, because the [cache key](#cache-keys) includes the build (or `deploymentId`) ID.

For data that needs to persist across deploys, use [`unstable_cache`](/docs/app/api-reference/functions/unstable_cache) for non-`fetch` functions or the [`fetch`](/docs/app/api-reference/functions/fetch) cache.

Very rarely, for compliance requirements or when you can't refactor your code to pass runtime data as arguments to a `use cache` scope, you might need [`use cache: private`](/docs/app/api-reference/directives/use-cache-private).

###### Draft Mode

When [Draft Mode](/docs/app/guides/draft-mode) is enabled, all cached functions and components re-execute on every request, and results are not saved to the cache. This ensures draft content is always fresh without requiring any changes to your caching code.

You can read `isEnabled` from [`draftMode()`](/docs/app/api-reference/functions/draft-mode) inside a `use cache` scope, however, other runtime APIs like `cookies()` and `headers()` are not allowed, even when Draft Mode is active. See [Passing runtime values to cached functions](/docs/app/getting-started/caching#passing-runtime-values-to-cached-functions) for the recommended pattern.

app/components/content.tsx

Calling `enable()` or `disable()` inside a caching directive scope will also throw an error. Draft Mode can only be toggled in [Route Handlers](/docs/app/api-reference/file-conventions/route) or [Server Actions](/docs/app/getting-started/mutating-data).

###### React.cache isolation

[`React.cache`](https://react.dev/reference/react/cache) operates in an isolated scope inside `use cache` boundaries. Values stored via `React.cache` outside a `use cache` function are not visible inside it.

This means you cannot use `React.cache` to pass data into a `use cache` scope:

This isolation ensures cached functions have predictable, self-contained behavior. To pass data into a `use cache` scope, use function arguments instead.

##### `use cache` at runtime

On the  **server** , cache entries are stored in-memory and respect the `revalidate` and `expire` times from your `cacheLife` configuration. You can customize the cache storage by configuring [`cacheHandlers`](/docs/app/api-reference/config/next-config-js/cacheHandlers) in your `next.config.js` file.

On the  **client** , content from the server cache is stored in the browser's memory for the duration defined by the `stale` time. The client router enforces a  **minimum 30-second stale time** , regardless of configuration.

The `x-nextjs-stale-time` response header communicates cache lifetime from server to client, ensuring coordinated behavior.

##### Revalidation

Cached functions revalidate based on the `revalidate` and `expire` times in their `cacheLife` profile, or on-demand through tags. These two approaches are not mutually exclusive and are often paired:

- **[Time-based](#time-based-revalidation)** : refresh automatically after a set duration with [`cacheLife`](/docs/app/api-reference/functions/cacheLife).

- **[On-demand](#on-demand-revalidation)** : invalidate after a mutation with [`cacheTag`](/docs/app/api-reference/functions/cacheTag) and [`revalidateTag`](/docs/app/api-reference/functions/revalidateTag) or [`updateTag`](/docs/app/api-reference/functions/updateTag).

For example, a blog post that changes only when its author edits it can use a long `cacheLife` like `max` with a `cacheTag`, then invalidate on demand when the post is saved. A list of recent posts that updates throughout the day can use a shorter profile like `hours` to refresh on its own, without manual invalidation.

###### Time-based revalidation

Set an explicit cache lifetime with [`cacheLife`](/docs/app/api-reference/functions/cacheLife) in every `use cache` scope. It makes the cache behavior clear at the call site, instead of depending on the `default` profile or surrounding caches.

lib/data.ts

If you omit `cacheLife`, the `default` profile applies and the lifetime is no longer explicit at the call site:

- **stale** : 5 minutes (client-side)

- **revalidate** : 15 minutes (server-side)

- **expire** : never expires by time

lib/data.ts

Nesting a short-lived use cache inside one without an explicit [cacheLife](/docs/app/api-reference/functions/cacheLife) fails the build during prerendering. See [Nested short-lived caches](/docs/app/api-reference/functions/cacheLife#nested-short-lived-caches) for the rule and fix.

###### On-demand revalidation

Use [`cacheTag`](/docs/app/api-reference/functions/cacheTag), [`updateTag`](/docs/app/api-reference/functions/updateTag), or [`revalidateTag`](/docs/app/api-reference/functions/revalidateTag) for on-demand cache invalidation:

lib/data.ts
app/actions.ts

Both `cacheLife` and `cacheTag` integrate across client and server caching layers, meaning you configure your caching semantics in one place and they apply everywhere.

##### Examples

###### Caching an entire route with `use cache`

To prerender an entire route, add `use cache` to the top of  **both**  the `layout` and `page` files. Each of these segments are treated as separate entry points in your application, and will be cached independently.

app/layout.tsxTypeScriptJavaScriptTypeScript

Any components imported and nested in `page` file are part of the cache output associated with the `page`.

app/page.tsxTypeScriptJavaScriptTypeScript

> **Good to know** :
>
>
>
>
>
>
> - If `use cache` is added only to the `layout` or the `page`, only that route segment and any components imported into it will be cached.

###### Caching a component's output with `use cache`

You can use `use cache` at the component level to cache any fetches or computations performed within that component. The cache entry will be reused as long as the serialized props produce the same value in each instance.

app/components/bookings.tsxTypeScriptJavaScriptTypeScript

###### 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, a database query, or a slow computation.

app/actions.tsTypeScriptJavaScriptTypeScript

> **Good to know:**  When a cached directive (`use cache`, [`use cache: private`](/docs/app/api-reference/directives/use-cache-private), or [`use cache: remote`](/docs/app/api-reference/directives/use-cache-remote)) is at the top of a file, you can import its exported functions into a Client Component and call them directly; they run on the server and return the result, similar to a [Server Function](/docs/app/glossary#server-function). Prefer calling cached functions on the server and passing results down as props.

###### Interleaving

In React, composition with `children` or slots is a well-known pattern for building flexible components. When using `use cache`, you can continue to compose your UI in this way. Anything included as `children`, or other compositional slots, in the returned JSX will be passed through the cached component without affecting its cache entry.

As long as you don't directly reference any of the JSX slots inside the body of the cacheable function itself, their presence in the returned output won't affect the cache entry.

app/page.tsxTypeScriptJavaScriptTypeScript

You can also pass Server Actions through cached components to Client Components without invoking them inside the cacheable function.

app/page.tsxTypeScriptJavaScriptTypeScript

app/ClientComponent.tsxTypeScriptJavaScriptTypeScript

##### Troubleshooting

###### Debugging cache behavior

###### Verbose logging

Set `NEXT_PRIVATE_DEBUG_CACHE=1` for verbose cache logging:

> **Good to know:**  This environment variable also logs ISR and other caching mechanisms. See [Verifying correct production behavior](/docs/app/guides/incremental-static-regeneration#verifying-correct-production-behavior) for more details.

###### Console log replays

In development, console logs from cached functions appear with a `Cache` prefix.

###### Build Hangs (Cache Timeout)

If your build hangs, you're accessing Promises that resolve to uncached or runtime data, created outside a `use cache` boundary. The cached function waits for data that can't resolve during the build, causing a timeout after 50 seconds.

When the build timeouts you'll see this error message:

> Error: Filling a cache during prerender timed out, likely because request-specific arguments such as params, searchParams, cookies() or uncached data were used inside "use cache".

Common ways this happens: passing such Promises as props, accessing them via closure, or retrieving them from shared storage (Maps).

> **Good to know:**  Directly calling `cookies()` or `headers()` inside `use cache` fails immediately with a [different error](/docs/messages/next-request-in-use-cache), not a timeout.

 **Passing runtime data Promises as props:**

app/page.tsx

Await the `cookies` store in the `Dynamic` component, and pass a cookie value to the `Cached` component.

 **Shared deduplication storage:**

app/page.tsx

Use Next.js's built-in `fetch()` deduplication or use separate Maps for cached and uncached contexts.

##### Platform Support

| Deployment Option | Supported |
| --- | --- |

| [Node.js server](/docs/app/getting-started/deploying#nodejs-server) | Yes |
| [Docker container](/docs/app/getting-started/deploying#docker) | Yes |
| [Static export](/docs/app/getting-started/deploying#static-export) | No |
| [Adapters](/docs/app/getting-started/deploying#adapters) | Platform-specific |

Learn how to [configure caching](/docs/app/guides/self-hosting#caching-and-isr) when self-hosting Next.js.

##### Version History

| Version | Changes |
| --- | --- |

| `v16.0.0` | `"use cache"` is enabled with the Cache Components feature. |
| `v15.0.0` | `"use cache"` is introduced as an experimental feature. |

##### Related

View related API references.[### use cache: private

Learn how to use the "use cache: private" directive to cache functions that access runtime request APIs.](/docs/app/api-reference/directives/use-cache-private)[### cacheComponents

Learn how to enable the cacheComponents flag in Next.js.](/docs/app/api-reference/config/next-config-js/cacheComponents)[### cacheLife

Learn how to set up cacheLife configurations in Next.js.](/docs/app/api-reference/config/next-config-js/cacheLife)[### cacheHandlers

Configure custom cache handlers for use cache directives in Next.js.](/docs/app/api-reference/config/next-config-js/cacheHandlers)[### cacheTag

Learn how to use the cacheTag function to manage cache invalidation in your Next.js application.](/docs/app/api-reference/functions/cacheTag)[### cacheLife

Learn how to use the cacheLife function to set the cache expiration time for a cached function or component.](/docs/app/api-reference/functions/cacheLife)[### revalidateTag

API Reference for the revalidateTag function.](/docs/app/api-reference/functions/revalidateTag)

Was this helpful?

supported.Send

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  cacheComponents: true,
}

export default nextConfig

// 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
}

async function Component({ userId }: { userId: string }) {
  const getData = async (filter: string) => {
    'use cache'
    // Cache key includes both userId (from closure) and filter (argument)
    return fetch(`/api/users/${userId}/data?filter=${filter}`)
  }

  return getData('active')
}

// Valid - primitives and plain objects
async function UserCard({
  id,
  config,
}: {
  id: string
  config: { theme: string }
}) {
  'use cache'
  return
{id}

}

// Invalid - class instance
async function UserProfile({ user }: { user: UserClass }) {
  'use cache'
  // Error: Cannot serialize class instance
  return
{user.name}

}

async function CachedWrapper({ children }: { children: ReactNode }) {
  'use cache'
  // Don't read or modify children - just pass it through
  return (

      Cached Header
      {children}

  )
}

// Usage: children can be dynamic
export default function Page() {
  return (
    <CachedWrapper>
      <DynamicComponent /> {/* Not cached, passed through */}
    </CachedWrapper>
  )
}

async function CachedForm({ action }: { action: () => Promise<void> }) {
  'use cache'
  // Don't call action here - just pass it through
  return <form action={action}>{/* ... */}</form>
}

import { draftMode } from 'next/headers'

async function Content() {
  'use cache'

  const { isEnabled } = await draftMode()
  const url = isEnabled
    ? 'https://draft.example.com/content'
    : 'https://production.example.com/content'

  const data = await fetch(url)
  return <article>{/* ... */}</article>
}

import { cache } from 'react'

const store = cache(() => ({ current: null as string | null }))

function Parent() {
  const shared = store()
  shared.current = 'value from parent'
  return <Child />
}

async function Child() {
  'use cache'
  const shared = store()
  // shared.current is null, not 'value from parent'
  // use cache has its own isolated React.cache scope
  return <div>{shared.current}</div>
}

import { cacheLife } from 'next/cache'

async function getData() {
  'use cache'
  cacheLife('hours') // Use built-in 'hours' profile
  return fetch('/api/data')
}

async function getData() {
  'use cache'
  // Implicitly uses the 'default' profile
  return fetch('/api/data')
}

import { cacheTag } from 'next/cache'

async function getProducts() {
  'use cache'
  cacheTag('products')
  return fetch('/api/products')
}

'use server'

import { updateTag } from 'next/cache'

export async function updateProduct() {
  await db.products.update(...)
  updateTag('products') // Invalidates all 'products' caches
}

'use cache'

export default async function Layout({ children }: { children: ReactNode }) {
  return <div>{children}</div>
}

'use cache'

async function Users() {
  const users = await fetch('/api/users')
  // loop through users
}

export default async function Page() {
  return (
    <main>
      <Users />
    </main>
  )
}

export async function Bookings({ type = 'haircut' }: BookingsProps) {
  'use cache'
  async function getBookingsData() {
    const data = await fetch(`/api/bookings?type=${encodeURIComponent(type)}`)
    return data
  }
  return //...
}

interface BookingsProps {
  type: string
}

export default async function Page() {
  const uncachedData = await getData()
  return (
    // Pass compositional slots as props, e.g. header and children
    <CacheComponent header={
Home
}>
      {/* DynamicComponent is provided as the children slot */}
      <DynamicComponent data={uncachedData} />
    </CacheComponent>
  )
}

async function CacheComponent({
  header, // header: a compositional slot, injected as a prop
  children, // children: another slot for nested composition
}: {
  header: ReactNode
  children: ReactNode
}) {
  'use cache'
  const cachedData = await fetch('/api/cached-data')
  return (

      {header}
      <PrerenderedComponent data={cachedData} />
      {children}

  )
}

import ClientComponent from './ClientComponent'

export default async function Page() {
  const performUpdate = async () => {
    'use server'
    // Perform some server-side update
    await db.update(...)
  }

  return <CachedComponent performUpdate={performUpdate} />
}

async function CachedComponent({
  performUpdate,
}: {
  performUpdate: () => Promise<void>
}) {
  'use cache'
  // Do not call performUpdate here
  return <ClientComponent action={performUpdate} />
}

'use client'

export default function ClientComponent({
  action,
}: {
  action: () => Promise<void>
}) {
  return <button onClick={action}>Update</button>
}

NEXT_PRIVATE_DEBUG_CACHE=1 npm run dev
# or for production
NEXT_PRIVATE_DEBUG_CACHE=1 npm run start

import { cookies } from 'next/headers'
import { Suspense } from 'react'

export default function Page() {
  return (
    <Suspense fallback={
Loading...
}>
      <Dynamic />
    </Suspense>
  )
}

async function Dynamic() {
  const cookieStore = cookies()
  return <Cached promise={cookieStore} /> // Build hangs
}

async function Cached({ promise }: { promise: Promise<unknown> }) {
  'use cache'
  const data = await promise // Waits for runtime data during build
  return
..

}

// Problem: Map stores dynamic Promises, accessed by cached code
import { Suspense } from 'react'

const cache = new Map<string, Promise<string>>()

export default function Page() {
  return (
    <>
      <Suspense fallback={
Loading...
}>
        <Dynamic id="data" />
      </Suspense>
      <Cached id="data" />
    </>
  )
}

async function Dynamic({ id }: { id: string }) {
  // Stores dynamic Promise in shared Map
  cache.set(
    id,
    fetch(`https://api.example.com/${id}`).then((r) => r.text())
  )
  return
Dynamic

}

async function Cached({ id }: { id: string }) {
  'use cache'
  return
{await cache.get(id)}
 // Build hangs - retrieves dynamic Promise
}


use cache: private

Summary: This page documents the 'use cache: private' directive in Next.js, which allows functions to access runtime request APIs within a cached scope while caching results only in the browser's memory and…

Overview

The `'use cache: private'` directive allows functions to access runtime request APIs like `cookies()`, `headers()`, and `searchParams` within a cached scope. However, results are **never stored on…

Usage

To use `'use cache: private'`, enable the [`cacheComponents`](/docs/app/api-reference/config/next-config-js/cacheComponents) flag in your `next.config.ts` file:

Then add `'use cache: private'` to…

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  cacheComponents: true,
}

export default nextConfig

Basic example

In this example, we demonstrate that you can access cookies within a `'use cache: private'` scope:

> **Good to know** : The `stale` time must be at least 30 seconds for per-link prefetching to work,…

import { Suspense } from 'react'
import { cookies } from 'next/headers'
import { cacheLife, cacheTag } from 'next/cache'

export async function generateStaticParams() {
  return [{ id: '1'…

Request APIs allowed in private caches

The following request-specific APIs can be used inside `'use cache: private'` functions:

| API | Allowed in `use cache` | Allowed in `'use cache: private'` |
| --- | --- | --- |
| `cookies()` | No |…

Version History

| Version | Changes |
| --- | --- |
| `v16.0.0` | `"use cache: private"` is enabled with the Cache Components feature. |

Related

View related API references.

- [### use cache - Learn how to use the "use cache" directive to cache data in your Next.js application.](/docs/app/api-reference/directives/use-cache)
- [###…