Clarifying that:
> - **`stale` from 30 seconds up to 5 minutes**: included in prerenders,
but excluded from the route's [App Shell](/docs/app/glossary#app-shell).
Means, 30 <= stale and stale < 5minutes
- Adding
docs/01-app/03-api-reference/05-config/01-next-config-js/cacheMaxMemorySize.mdx
- Various use cache snippet fixes
- Break nuance for fetch default
- Point to correct turbopack cache flags
- Lead use cache Revalidation with explicit cacheLife; split into
Time-based and On-demand.
- Recommend cacheLife in every use cache scope; drop "optional."
- Reorder cacheLife reference: Overriding before Custom; reword both.
- Document that overrides reach the generated cacheLife type signature.
- Add the override option to the config reference and migration guide.
### What?
Update the "Good to know" callout in the `cacheLife` docs to explicitly
state that `cacheLife()` must be called inside a function body, not at
module scope, and that doing so throws an error.
### Why?
Calling `cacheLife('days')` at module scope in a file with `'use cache'`
at the top throws: `` `cacheLife()` can only be called inside a "use
cache" function ``. This is technically correct (module scope is not
inside a function), but the previous docs only said `cacheLife` "should
be placed within the function" without mentioning it errors. Both
developers and AI agents hit this when they place `cacheLife()` next to
the file-level `'use cache'` directive at the top of the module.
### How?
Replaced the soft "should be placed within the function" language with
explicit "must be called inside a function body, not at module scope"
and noted that it throws an error otherwise.
## PR checklist (Improving Documentation)
- [x] Run `pnpm prettier-fix` to fix formatting issues before opening
the PR
- [x] Follow the docs contribution guide:
https://nextjs.org/docs/community/contribution-guide
Made with [Cursor](https://cursor.com)
---------
Co-authored-by: Joseph <joseph.chamochumbi@vercel.com>
This PRs unifies the caching story across the docs, making Cache
Components the happy path, while still providing guidance to users in
the old model. However, instead of explaining the old model and its
caching layers, we've created a new guide focusing on what APIs to use
and when.
This follow-up PR aligns terminology across the docs:
https://github.com/vercel/next.js/pull/90589
## IA updates
Getting Started section:
- Improves Getting Started progression:
- **Before:** CC → Fetching Data → Updating Data → Caching and
Revalidating (old and new model mixed)
- **After:** Fetching Data (Dynamic) → Mutating Data (Dynamic) → Caching
with CC (Prerendering) → Revalidating with CC.
- New: `caching.mdx` (CC-first)
- Structure:
- Enabling Cache Components
- Data vs UI-level caching
- Working with request time APIs
- Passing request values to cached functions
- Working with non-deterministic operations
- Working with synchronous operations
- How rendering works (PPR and static shell story)
- New: `revalidating.mdx` (CC-first)
- Explains how to use `cacheLife` and `cacheTag`
Guides Section:
- New: `caching-and-revalidating.mdx` (Previous Model)
- For users who are not using CC, includes `fetch` options and route
segment config
- Moves route segment config options that don't apply to CC from API
reference to this guide (for easy archiving in the future).
- New: `migrating-to-cache-components.mdx` (WIP)
- Del: `caching.mdx` 😌
## Terminology
We should remove caching layers from the docs. Users only needed to be
exposed to them when they were configured independently, but the new CC
APIs work across layers.
To make it easier to review this PR, I'm consolidating terminology and
fixing broken links in a new PR:
https://github.com/vercel/next.js/pull/90589
---------
Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
Co-authored-by: Joseph <joseph.chamochumbi@vercel.com>
## Summary
- Add note that omitting `expire` in `cacheLife` results in cache never
expiring
- Fix `default` preset table: `expire` was documented as "1 year" but
actual code uses `INFINITE_CACHE` (never)
- Add mention of expire omission behavior in custom profiles section
## Why
The `expire` property is optional (`expire?: number`), but the
documentation didn't explain
what happens when it's omitted. The source code shows it defaults to
`INFINITE_CACHE` (0xfffffffe),
meaning the cache never expires. Additionally, the preset profile table
incorrectly listed
the `default` profile's expire as "1 year" when the actual value is
`INFINITE_CACHE`.
### Source code references
- `packages/next/src/lib/constants.ts:45` — `INFINITE_CACHE =
0xfffffffe`
- `packages/next/src/server/config-shared.ts:1580` — `default.expire:
INFINITE_CACHE`
- `packages/next/src/server/use-cache/cache-life.ts:156` — only sets
`explicitExpire` when `expire !== undefined`
- `packages/next/src/server/use-cache/use-cache-wrapper.ts:477-479` —
falls back to `defaultCacheLife.expire` (INFINITE_CACHE)
---------
Co-authored-by: Joseph <joseph.chamochumbi@vercel.com>
This PR adds error handling for nested `"use cache"` where the inner
cache has a very short lifetime (zero `revalidate` or `expire` under 5
minutes) but the outer cache doesn't have an explicit `cacheLife()`
call.
Short-lived caches become "dynamic holes" that are excluded from
prerenders. When such a cache is nested inside another `"use cache"`
without an explicit `cacheLife`, the outer cache's lifetime would
silently become short too via
[propagation](https://nextjs.org/docs/app/api-reference/functions/cacheLife#nested-caching-behavior),
which can lead to unexpected behavior. To prevent this accidental
misconfiguration, Next.js now throws an error during prerendering,
requiring developers to explicitly declare their intent by adding
`cacheLife()` to the outer cache.
The implementation tracks whether `revalidate` and `expire` were
explicitly set via `hasExplicitRevalidate` and `hasExplicitExpire` flags
on the collected cache result. Errors are wrapped with
`wrapAsInvalidDynamicUsageError` to capture proper stack traces and
prevent userland try/catch from suppressing the build error.
Documentation has been updated with a new "Prerendering behavior"
section in the `cacheLife` API reference explaining how short-lived
caches become dynamic holes, and a "Nested short-lived caches"
subsection with examples showing how to fix the error.
closes NAR-761
Remove redundant example code for overriding cache profiles.
## For Contributors
### Improving Documentation
- Run `pnpm prettier-fix` to fix formatting issues before opening the
PR. ✅ (no changes)
- Read the Docs Contribution Guide to ensure your contribution follows
the docs guidelines:
https://nextjs.org/docs/community/contribution-guide✅
### What?
Remove a redundant example in the `cacheLife` docs.
### Why?
Because the redundant example is confusing.
### How?
Closes NEXT-
Fixes #
-->
As part of stabilizing `cacheComponents`, `cacheLife` profiles should
also be accessible from a top-level config. This updates the
configuration, adds the warning, and updates relevant docs.
This moves `experimental.cacheComponents` to a top level config. As part
of this, I disabled some tests in `build-output-prerender` that assert
on `cacheComponents` appearing in the experimental list. In a separate
PR, I'm going to show that Cache Components is enabled next to the
bundler info.
This also updates some docs pages to remove "experimental" language.
## What?
Rename `experimental.dynamicIO` to `experimental.cacheComponents` across
the Next.js codebase.
## Why?
We're going to be merging the functionality of the `ppr`, `dynamicIO`
and `useCache` experimental flags into the singular `cacheComponents`
flag to reduce complexity of the codebase and simplify adoption for
users wanting to experiment with experimental features.
## How?
- Renamed the configuration option from `experimental.dynamicIO` to
`experimental.cacheComponents`
- Added deprecation handling with automatic migration for the old option
name
- Updated all documentation, tests, and internal references
- Updated Rust code in SWC transforms and Turbopack
- Maintained backward compatibility with deprecation warnings
NAR-158
### What?
This pull request addresses two minor documentation issues in the
Next.js project:
1. A typo fix in the API reference for the `cacheLife` function.
2. A correction of an incorrect URL for the `experimental.typedRoutes`
in the Turbopack documentation.
### Why?
Accurate documentation is crucial for developers to effectively use the
features of Next.js. By ensuring the clarity and correctness of these
documents, we improve the user experience and aid in preventing
potential confusion when navigating and implementing the API features.
### How?
- **Typo Correction**: In
`docs/01-app/03-api-reference/04-functions/cacheLife.mdx`, the
`cacheLife` function documentation had a capitalization error in the
phrase “The `cacheLife` function.” This has been corrected to use the
correct lowercase styling: “the `cacheLife` function”.
- **URL Correction**: In
`docs/01-app/03-api-reference/08-turbopack.mdx`, the link pointing to
`experimental.typedRoutes` was incorrect. The link has been updated to
the correct URL:
`https://nextjs.org/docs/app/api-reference/next-config-js/typedRoutes`.
These changes ensure the accuracy and readability of the documentation,
aligning it with Next.js standards.
---
---------
Co-authored-by: Sam Ko <sam@vercel.com>