A comprehensive demo showcasing the latest Next.js 16 caching features including Cache Components, ISR (Incremental Static Regeneration), and Partial Prerendering (PPR).
- ✅
'use cache'directive - Explicit caching at component level - ✅
cacheLife()API - Control cache duration with preset profiles - ✅
cacheTag()API - Tag cached content for granular invalidation - ✅
revalidateTag()- On-demand cache revalidation with stale-while-revalidate - ✅
revalidatePath()- Path-based cache invalidation
- All pages use async React Server Components
- Direct data fetching without client-side JavaScript
- Streaming and Suspense for progressive rendering
- Mix static (cached) and dynamic (uncached) content in the same page
- Product detail pages demonstrate PPR in action
- Static product data + dynamic timestamps
app/
├── page.tsx # Home page with feature overview
├── products/
│ ├── page.tsx # Products listing (cached with 'use cache')
│ └── [id]/page.tsx # Product detail page (PPR demo)
├── admin/
│ └── page.tsx # Admin dashboard (fully dynamic)
├── actions/
│ └── revalidate.ts # Server Actions for cache control
└── globals.css # Styling with Pure.css
lib/
└── data.ts # Mock product data source
next.config.ts # Cache Components enabled
-
Install dependencies:
pnpm install
-
Start the development server:
pnpm dev
-
Open your browser:
http://localhost:3000
-
Visit the Products page (
/products)- Note the "Data Fetched" timestamp
- Refresh the page multiple times
- Expected: Timestamp stays the same (page is cached!)
-
Go to Admin Dashboard (
/admin)- Click "Revalidate All Products (revalidateTag)"
- Return to
/productsand refresh - Expected: New timestamp (cache was invalidated!)
-
Visit a product detail page (
/products/1)- Observe two sections:
- Static (Cached): Product details with a fixed timestamp
- Dynamic (Uncached): "Current Server Time" section
- Observe two sections:
-
Refresh the page multiple times
- Expected:
- Product "Last Updated" timestamp stays the same
- "Current Server Time" updates on every refresh
- This demonstrates PPR - mixing cached and dynamic content!
- Expected:
- View product 1 (
/products/1) - note its timestamp - Go to Admin (
/admin) - Click "Revalidate Product 1"
- Return to
/products/1and refresh- Expected: Product timestamp updated
- Note: Products listing
/productsis NOT affected (granular control!)
- View products listing - note stock levels
- Go to Admin Dashboard
- Click "Update Stock for Product 1"
- Return to products listing
- Expected: Stock level changed after cache revalidation
Traditional ISR (Next.js 15 and earlier):
export const revalidate = 3600; // Time-based onlyCache Components (Next.js 16):
'use cache'
import { cacheLife, cacheTag } from 'next/cache';
export default async function Page() {
cacheLife('hours'); // Flexible cache duration
cacheTag('products'); // Granular invalidation
// ...
}- Static with Long Cache - Use
cacheLife('days')for rarely changing content - Stale-While-Revalidate - Use
cacheLife('hours')for frequently updated content - Dynamic - Don't use
'use cache'for user-specific or real-time data - Hybrid (PPR) - Combine cached components with
Suspenseboundaries for dynamic content
'use server'
import { revalidateTag } from 'next/cache';
export async function updateProduct(id: string) {
await db.update(id);
revalidateTag(`product-${id}`); // Invalidate specific product
revalidateTag('products'); // Invalidate listing
}- Next.js 16 (canary) - Latest features
- React 19.2.0 - React Server Components
- TypeScript 5 - Type safety
- Pure.css 3.0 - Minimal CSS framework
- Biome - Fast linter and formatter
The app uses these cache life profiles:
- 'hours': stale=3600s, revalidate=900s (default for most content)
- 'days': For long-lived static content
- 'minutes': For frequently changing content
Custom profiles can be defined:
cacheLife({
stale: 3600, // Serve stale content for 1 hour
revalidate: 900, // Revalidate in background after 15 min
expire: 86400, // Hard expiration after 1 day
});-
Build the app:
pnpm build
-
Start production server:
pnpm start
-
Deploy to Vercel:
vercel deploy
- This demo uses mock data stored in memory - refresh the server to reset
- Cache Components require Next.js 16 with
cacheComponents: true - All async request APIs (
cookies(),headers(),params) requireawaitin Next.js 16 - The dev server automatically restarts when config changes
MIT