CacheHandler set() method
The set() method stores a cache entry for a given cache key. Signature: set(cacheKey: string, pendingEntry: Promise<CacheEntry>): Promise<void>. Parameters: cacheKey is a string for the unique key to store the entry under; pendingEntry is a Promise<CacheEntry> that may still be pending when called. The handler must await the pendingEntry promise before storing it, since the cache entry may still be generating. Once resolved, the entry should be stored in the cache system.
CacheHandler get() method
The get() method retrieves a cache entry for a given cache key. Signature: get(cacheKey: string, softTags: string[]): Promise<CacheEntry | undefined>. Parameters: cacheKey is a string with the unique key for the cache entry; softTags is a string array of implicit tags derived from the route path. Returns a CacheEntry object if found, or undefined if not found or expired. The handler should retrieve the cache entry from storage, check if it has expired based on the revalidate time, and return undefined for missing or expired entries.
Handler types in cacheHandlers
Two handler types can be configured: `default` is used by the 'use cache' directive, and `remote` is used by the 'use cache: remote' directive. If cacheHandlers is not configured, Next.js uses an in-memory LRU (Least Recently Used) cache for both default and remote. Additional named handlers (e.g., 'sessions', 'analytics') can be defined and referenced with 'use cache: <name>'.
When custom cache handlers are needed
Most applications do not need custom cache handlers. The default in-memory cache works well for typical use cases. Custom handlers are for advanced scenarios: sharing cache across multiple instances by integrating with shared storage systems like Redis, Memcached, or DynamoDB; or changing storage type to disk, database, or external services for persistence, reduced memory usage, or infrastructure integration.
cacheHandlers config option
The `cacheHandlers` configuration in next.config.ts or next.config.js allows you to define custom cache storage implementations for 'use cache' and 'use cache: remote' directives. 'use cache: private' is not configurable. Configuration is an object with optional `default` and `remote` properties, each taking a file path resolved via require.resolve(). Example: { cacheHandlers: { default: require.resolve('./cache-handlers/default-handler.js'), remote: require.resolve('./cache-handlers/remote-handler.js') } }
htmlLimitedBots version history
htmlLimitedBots option was introduced in Next.js version 15.2.0.
htmlLimitedBots config example
Example configuration in next.config.ts:
import type { NextConfig } from 'next'
const config: NextConfig = {
htmlLimitedBots: /MySpecialBot|MyAnotherSpecialBot|SimpleCrawler/,
}
export default config
htmlLimitedBots disable streaming metadata
To fully disable streaming metadata and send blocking metadata to all bots, set htmlLimitedBots to /.*/
htmlLimitedBots overrides default list
Specifying a htmlLimitedBots config will override the Next.js default list. This is advanced behavior and the default should be sufficient for most cases.
htmlLimitedBots default list
Next.js includes a default list of HTML limited bots including Google crawlers (Mediapartners-Google, AdsBot-Google, Google-PageRenderer), Bingbot, Twitterbot, and Slackbot.
htmlLimitedBots config option
The htmlLimitedBots config option allows you to specify a list of user agents that should receive blocking metadata instead of streaming metadata. It accepts a regular expression pattern. The value is set in next.config.ts or next.config.js.
fetch() polyfill in Node.js prior to 18
In Node.js versions prior to 18, Next.js automatically polyfills fetch() with undici.
httpAgentOptions keepAlive example
To disable HTTP Keep-Alive for all fetch() calls on the server-side, add this configuration to next.config.js: module.exports = { httpAgentOptions: { keepAlive: false, }, }
HTTP Keep-Alive default behavior in Next.js
In Node.js versions prior to 18, Next.js automatically enables HTTP Keep-Alive by default for fetch() calls on the server-side.
httpAgentOptions config option
The httpAgentOptions config option in next.config.js controls HTTP agent behavior for server-side fetch() calls. It can be used to disable HTTP Keep-Alive by setting keepAlive to false.
Custom image loader configuration in next.config.js
To use a custom image loader instead of Next.js built-in Image Optimization API, configure next.config.js with the images object. Set loader to 'custom' and loaderFile to a relative path pointing to a file from the root of the Next.js application. The loaderFile must export a default function that returns a string.
IMAGE cache entry kind properties
When handling image cache entries, the kind property will be 'IMAGE' and the data will include buffer, etag, extension, and revalidate properties.
cacheHandler platform support
cacheHandler is supported on Node.js server and Docker container deployments. It is not supported for static export. Support for adapters is platform-specific.
cacheHandler version history
Version v16.2.0 added cacheHandler support for image optimization caching. Version v14.1.0 renamed incrementalCacheHandlerPath to cacheHandler and made it stable. Version v13.4.0 added support for revalidateTag and standalone output. Version v12.2.0 introduced experimental incrementalCacheHandlerPath.
cacheHandler revalidateTag() method signature
The revalidateTag() method accepts tag (string or string array) parameter specifying the cache tags to revalidate. The method returns Promise<void>.
cacheHandler image optimization caching configuration
To enable cacheHandler for caching optimized images from next/image, set images.customCacheHandler to true in next.config.js: module.exports = { cacheHandler: require.resolve('./cache-handler.js'), images: { customCacheHandler: true, }, }
revalidatePath calls revalidateTag under the hood
revalidatePath is a convenience layer on top of cache tags. Calling revalidatePath will call your cacheHandler's revalidateTag function, which you can then choose to tag cache keys based on the path.
cacheHandler resetRequestCache() method signature
The resetRequestCache() method resets the temporary in-memory cache for a single request before the next request. It takes no parameters and returns void.
cacheHandler set() method signature
The set() method accepts key (string), data (Data or null), and ctx (object with tags array) parameters. The data object contains a kind property indicating the type of cache entry. For image optimization, kind will be 'IMAGE' and data will include properties like buffer, etag, extension, and revalidate. The method returns Promise<void>.
cacheHandler get() method signature
The get() method accepts key (string) and ctx (object) parameters. The ctx parameter contains a kind property indicating the type of cache entry being retrieved. Possible kind values are 'APP_PAGE', 'APP_ROUTE', 'PAGES', 'FETCH', and 'IMAGE'. The method returns the cached value or null if not found.
cacheHandler API methods
The cache handler must implement the following methods: get(), set(), revalidateTag(), and resetRequestCache().
cacheHandler basic configuration example
To use a custom cache handler, set cacheHandler to the path of your cache handler file, and optionally set cacheMaxMemorySize to 0 to disable default in-memory caching: module.exports = { cacheHandler: require.resolve('./cache-handler.js'), cacheMaxMemorySize: 0, }
cacheHandler is not used by 'use cache' directives
The cacheHandler configuration is specifically used by Next.js for server cache operations such as storing and revalidating ISR, route handler responses, and optimized images. It is not used by 'use cache' directives. For 'use cache' directives, use cacheHandlers (plural) instead.
cacheHandler config for persistent cache storage
The cacheHandler configuration option allows you to configure the Next.js cache location to persist cached pages and data to durable storage, or share the cache across multiple containers or instances of your Next.js application.
Configuration function with defaultConfig parameter
When exporting a function from next.config.js, the second parameter is an object containing { defaultConfig }, which provides access to Next.js default configuration values.
Unit testing next.config.js with experimental utilities
Starting in Next.js 15.1, the 'next/experimental/testing/server' package provides utilities for unit testing next.config.js files. The unstable_getResponseFromNextConfig function runs the headers, redirects, and rewrites functions from next.config.js with provided request information and returns a NextResponse with routing results. Note that the response only considers next.config.js fields and does not consider proxy or filesystem routes.
Phase parameter in configuration
The phase parameter in a configuration function represents the current context in which the configuration is loaded. Phases can be imported from 'next/constants', such as PHASE_DEVELOPMENT_SERVER, and allow you to apply different configuration for different build contexts.
Configuration as a function
next.config.js can export a function that receives phase and { defaultConfig } parameters, and returns the NextConfig object. This allows phase-specific configuration.
next.config.ts for TypeScript
You can use next.config.ts to write your Next.js configuration in TypeScript. Import the NextConfig type from 'next' and export the config with export default.
next.config.mjs for ECMAScript modules
To use ECMAScript modules, create next.config.mjs instead of next.config.js. Use export default instead of module.exports. The .cjs and .cts extensions are not currently supported.
next.config.js CommonJS format
The default format for next.config.js uses CommonJS with module.exports. The file is used by the Next.js server and build phases, and is not included in the browser build.
next.config.js file location and format
next.config.js is a regular Node.js module (not a JSON file) located in the root of your project directory, at the same level as package.json. It must have a default export.
unstable_getResponseFromNextConfig and getRedirectUrl example
Example of unit testing next.config.js:
```js
import {
getRedirectUrl,
unstable_getResponseFromNextConfig,
} from 'next/experimental/testing/server'
const response = await unstable_getResponseFromNextConfig({
url: 'https://nextjs.org/test',
nextConfig: {
async redirects() {
return [{ source: '/test', destination: '/test2', permanent: false }]
},
},
})
expect(response.status).toEqual(307)
expect(getRedirectUrl(response)).toEqual('https://nextjs.org/test2')
```
This example shows how to test the redirects configuration using the experimental testing utilities.
next.config.js does not support new JavaScript features beyond target Node.js version
Avoid using JavaScript features not available in your target Node.js version in next.config.js, because the file will not be parsed by Webpack or Babel.
Async configuration function
Since Next.js 12.1.0, next.config.js can export an async function. The function receives phase and { defaultConfig } parameters and must return the NextConfig object.
inlineCss limitations
The inlineCss feature has known limitations: CSS inlining is applied globally and cannot be configured on a per-page basis; styles are duplicated during initial page load, appearing once within <style> tags for SSR and once in the RSC payload; when navigating to prerendered pages, styles use <link> tags instead of inline CSS to avoid duplication; this feature is not available in development mode and only works in production builds.
When to enable inlineCss
Enable inlineCss if you use atomic CSS frameworks like Tailwind and want to optimize first-load performance for new visitors.
inlineCss not suitable for large CSS bundles
External stylesheets cache independently and load efficiently on modern infrastructure. Inlined CSS arrives with every HTML response, increasing Time to First Byte (TTFB) and preventing browsers from caching styles separately. This trade-off works for small CSS (atomic frameworks like Tailwind), but adds overhead for larger bundles like Bootstrap or Material UI.
When to skip inlineCss
Skip inlineCss if returning visitors are common and you want them to benefit from cached stylesheets.
inlineCss performance benefit for first-time visitors
Inlining CSS helps first-time visitors by eliminating the request waterfall where the browser must download HTML, parse it, discover CSS link tags, then request stylesheets before rendering. With inlined CSS, styles arrive with the HTML, allowing the browser to render immediately. This improves First Contentful Paint (FCP) and Largest Contentful Paint (LCP) metrics.
inlineCss works best with atomic CSS frameworks like Tailwind
Inlined CSS is most practical with atomic CSS frameworks like Tailwind because they generate only the classes you use, keeping CSS small. The styles for a page don't grow proportionally with page complexity—they remain compact regardless of how much UI you build. This makes inlining practical since you get the performance benefit without significantly bloating HTML.
inlineCss config option
The inlineCss configuration option is an experimental feature that enables inline CSS support in Next.js. When enabled by setting experimental.inlineCss to true, all places where a <link> tag would normally be generated will instead have a <style> tag generated. This applies CSS inline in the <head> rather than linking to external stylesheets.
inlineCss configuration syntax
To enable inlineCss in next.config.ts, use: const nextConfig: NextConfig = { experimental: { inlineCss: true } }. In next.config.js, use: const nextConfig = { experimental: { inlineCss: true } }.
inlineCss drawback for returning visitors
Inlined CSS cannot be cached separately from HTML, so every page load re-downloads the same CSS. Returning visitors who visit your site repeatedly would benefit from cached external stylesheets, but with inlining they re-download styles on every visit.
instrumentationClientInject plugin example
module.exports = function withMyInstrumentation(nextConfig = {}) {
return {
...nextConfig,
instrumentationClientInject: [
...(nextConfig.instrumentationClientInject ?? []),
'my-instrumentation-package/client',
],
}
}
This example shows a plugin that appends its own module to the existing instrumentationClientInject configuration.
onRouterTransitionStart export example in instrumentation module
// lib/sentry-client.js
// Side-effectful setup runs at load time.
setupSentry()
export function onRouterTransitionStart(url, navigationType) {
recordNavigationBreadcrumb(url, navigationType)
}
This example shows how an injected module can export onRouterTransitionStart to hook into router navigation events.
instrumentationClientInject plugin pattern
A plugin typically appends its own module to whatever the project already has configured by spreading the existing instrumentationClientInject array: ...nextConfig.instrumentationClientInject ?? [] followed by the plugin's module entries.
instrumentationClientInject execution order
Modules on the client run in this order: 1) Each entry in instrumentationClientInject in array order, 2) The project's instrumentation-client.{js,ts} file if present, 3) React hydration.
onRouterTransitionStart in injected instrumentation modules
Each injected module may optionally export an onRouterTransitionStart function. Next.js composes a single hook that fans out to every exported onRouterTransitionStart on each navigation, calling them in array order with the user file's hook running last. Modules that do not export onRouterTransitionStart are skipped during navigation.
instrumentationClientInject config option
instrumentationClientInject is a list of modules that are imported on the client for their side effects before the user's instrumentation-client.{js,ts} file runs, and before React hydration. Each entry is either a bare npm package name (resolved from node_modules) or a path relative to the project root.
instrumentationClientInject use case for plugins
instrumentationClientInject is primarily intended for next.config.js plugins like wrappers (withSentry, withAnalytics) that extend a project's config. It lets such plugins inject their own client instrumentation module including a navigation hook without requiring every project to author or modify an instrumentation-client file.
instrumentationClientInject direct configuration example
module.exports = {
instrumentationClientInject: [
'my-analytics-package',
'./lib/sentry-client.js',
],
}
This example shows how to set instrumentationClientInject directly in next.config.js with both npm package names and relative paths.
instrumentationClientInject introduced in version
instrumentationClientInject was introduced in Next.js v16.3.0.
logging config option overview
The logging configuration in next.config.js controls logging behavior in the terminal during Next.js development mode. It can be set to false to disable all development logging, or configured with specific options for fetches, server functions, incoming requests, and browser console logs.
logging.fetches.fullUrl option
The logging.fetches.fullUrl option enables logging the full URL for fetch requests in the console during development. It is a boolean option set within the logging.fetches object in next.config.js.