npx skills add ...
npx skills add vercel/nextjs-skills --skill next-cache-components
Next.js 16 Cache Components - PPR, use cache directive, cacheLife, cacheTag, updateTag
This repo is now called vercel-labs/next-skills. Both names install the same content, but the install count here only covers this one.
npx skills add vercel/nextjs-skills --skill next-cache-components
Cache Components enable Partial Prerendering (PPR) - mix static, cached, and dynamic content in a single route.
This replaces the old experimental.ppr flag.
With Cache Components enabled, content falls into three categories:
Synchronous code, imports, pure computations - prerendered at build time:
use cache)Async data that doesn't need fresh fetches every request:
Runtime data that must be fresh - wrap in Suspense:
use cache DirectivecacheLife() - Custom LifetimeBuilt-in profiles: 'default', 'minutes', 'hours', 'days', 'weeks', 'max'
cacheTag() - Tag Cached ContentupdateTag() - Immediate InvalidationUse when you need the cache refreshed within the same request:
revalidateTag() - Background RevalidationUse for stale-while-revalidate behavior:
Cannot access cookies(), headers(), or searchParams inside use cache.
use cache: privateFor compliance requirements when you can't refactor:
Cache keys are automatic based on:
| Old Config | Replacement |
|---|---|
experimental.ppr | cacheComponents: true |
dynamic = 'force-dynamic' | Remove (default behavior) |
dynamic = 'force-static' | 'use cache' + cacheLife('max') |
revalidate = N | cacheLife({ revalidate: N }) |
unstable_cache() | 'use cache' directive |
unstable_cache to use cacheunstable_cache has been replaced by the use cache directive in Next.js 16. When cacheComponents is enabled, convert unstable_cache calls to use cache functions:
Before (unstable_cache):
After (use cache):
Key differences:
use cache generates keys automatically from function arguments and closures. The keyParts array from unstable_cache is no longer needed.options.tags with cacheTag() calls inside the function.options.revalidate with cacheLife({ revalidate: N }) or a built-in profile like cacheLife('minutes').unstable_cache did not support cookies() or headers() inside the callback. The same restriction applies to use cache, but you can use 'use cache: private' if needed.Math.random(), Date.now()) execute once at build time inside use cacheFor request-time randomness outside cache:
Sources: