Cache Components and use cache
Cache Components is a new caching model introduced in Next.js 16. You turn it on with a setting, and it changes the approach: all data is dynamic by default, and you explicitly mark what may be stored with the 'use cache' directive. A page is then assembled from a static "shell" prepared in advance and dynamic parts that stream in. This approach is called Partial Prerendering.
Turning it on
Add the setting to next.config.ts and restart the development server:
// next.config.ts
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
cacheComponents: true,
};
export default nextConfig;Without this setting the 'use cache' directive and the functions in this lesson do not work.
Caching a data function
The 'use cache' directive at the start of an async function stores its result. Let us do that with the posts list:
// lib/posts.ts (fragment)
import { cacheLife, cacheTag } from 'next/cache';
export async function getPosts(): Promise<Post[]> {
'use cache';
cacheLife('hours');
cacheTag('posts');
return db.select().from(posts);
}cacheLife('hours') sets the lifetime — about an hour, cacheTag('posts') gives the result a tag. Function arguments are part of the cache key: getPost('a') and getPost('b') are stored separately. The home page and /posts now show the list from the cache.
cacheLife profiles
| Profile | What for |
|---|---|
'seconds' | Data that changes constantly |
'minutes' | Frequent updates |
'hours' | Several updates a day |
'days' | A daily update |
'weeks' | A weekly update |
'max' | Data that almost never changes |
Clearing after adding a post
In the createPost server action, after writing to the database, call updateTag('posts') from next/cache — the cache with that tag is dropped, and the new post shows up in the list immediately.
Uncached data goes into Suspense
Data without 'use cache' and reads of cookies() or headers() run on every request. Such a component must be wrapped in Suspense — like Comments in the streaming lesson:
// app/posts/[slug]/page.tsx (fragment)
<Suspense fallback={<p>Loading comments...</p>}>
<Comments />
</Suspense>The placeholder goes into the static shell, and the comments stream in. If you forget Suspense, the development server shows a hint about a blocking route.
What changes in the project
- The
dynamic,revalidateandfetchCacheexports from pages are no longer needed and cause an error —'use cache',cacheLifeandSuspensereplace them. dynamicParamsis not supported, andgenerateStaticParamsmust return at least one item.- The build table shows the
◐symbol — a page with a prebuilt shell and streamed parts.
The course is built on the regular model, because a new project is created without this setting. Turn on Cache Components deliberately, when you are ready to go through every page.
Common mistake
Calling cookies() inside a function with 'use cache'. The cache is shared by all visitors, so request data is not allowed inside it — Next.js throws an error. Read the cookie outside, in an uncached component, and pass the value into the cached function as an argument.