Skip to content

Commit 87a42f0

Browse files
authored
Next 16 support (#109)
* Upgraded nextjs in example project * Updated package dependencies * Ensure cache handler is used in dev mode * Merge branch 'master' into next16 * Bump * Merge dev and version bump * Ran migrations from next 16 docs * Fixed new lint issues * Fixed package json * Adjusted .env and added readme comment * Reworked example project (#160) * Reworked examples * Updated readme * F * Added new examples (#161) * Extra examples * Layout changes * Added unstable cache example * Version bump * Next 16 updateTag and cache profiles examples (incremental cache handler) (#162) * Added revalidate profile example * Added updateTag example * Added compatibility matrix * Readme improvements (#163) * Added compatibility matrix * Readme improvements * F * F * Merge fixes and readme update * Fix/next16 rsc issues (#199) * Added repro steps example * F * Ensures correct RSC data handling by prioritizing prefetch and fallback to page data. * Bumped versions * 3.0.0 * Updated readme
1 parent d1d531e commit 87a42f0

46 files changed

Lines changed: 4550 additions & 801 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 282 additions & 231 deletions
Large diffs are not rendered by default.

examples/redis-minimal/.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
NEXT_PRIVATE_DEBUG_CACHE="1"
22
REDIS_URL="redis://localhost:6379"
3-
REDIS_SINGLE_CONNECTION=true
3+
REDIS_SINGLE_CONNECTION=false
44
#INITIAL_CACHE_SET_ONLY_IF_NOT_EXISTS=true
55
# REDIS_TYPE can be "redis" (default, uses @redis/client) or "ioredis"
66
REDIS_TYPE="redis"

examples/redis-minimal/README.md

Lines changed: 227 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,37 @@
1-
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
1+
# Next.js Cache Handler Examples
2+
3+
This example application demonstrates various Next.js caching functionalities using the Redis cache handler. It provides a comprehensive UI to explore and test different caching strategies.
24

35
## Getting Started
46

5-
First, run the development server:
7+
First, install dependencies:
68

79
```bash
810
npm i
9-
npm run dev
1011
```
1112

12-
Or run build and run production server:
13+
### Important: Development vs Production Mode
14+
15+
**Next.js does not use the cache handler in development mode.** This is a Next.js limitation - caching is intentionally disabled in dev mode for faster hot reloading and to ensure developers always see fresh data.
16+
17+
To test caching functionality, you must use **production mode**:
1318

1419
```bash
15-
npm i
1620
npm run build
1721
npm run start
1822
```
1923

24+
For development (without caching):
25+
26+
```bash
27+
npm run dev
28+
```
29+
2030
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
2131

22-
Modify `.env` file if you need to.
32+
## Configuration
33+
34+
Modify the `.env` file if you need to configure Redis connection settings. The default Redis URL is used if not specified.
2335

2436
### Redis Client Configuration
2537

@@ -32,10 +44,214 @@ This allows you to test the `ioredisAdapter` functionality.
3244

3345
## Examples
3446

35-
- http://localhost:3000
36-
- http://localhost:3000/fetch-example
37-
- http://localhost:3000/static-params-test/cache
47+
The application includes several examples demonstrating different Next.js caching features:
48+
49+
### 1. Home Page (`/`)
50+
51+
Overview page listing all available examples with descriptions and features.
52+
53+
### 2. Default Cache (`/examples/default-cache`)
54+
55+
Demonstrates the default fetch caching behavior with `force-cache`.
56+
57+
**Features:**
58+
59+
- Default caching behavior (indefinite cache duration)
60+
- Perfect for static or rarely-changing data
61+
- Shows how Next.js caches by default
62+
63+
**Try it:**
64+
65+
- Visit `/examples/default-cache` to see cached data
66+
- The timestamp will remain the same on subsequent requests
67+
- Data is cached until manually cleared or build is redeployed
68+
69+
### 3. No Store (`/examples/no-store`)
70+
71+
Shows fetch with `no-store` option, which always fetches fresh data.
72+
73+
**Features:**
74+
75+
- Never caches responses
76+
- Always fetches fresh data from API
77+
- Perfect for real-time or user-specific data
78+
- Timestamp changes on every request
79+
80+
**Try it:**
81+
82+
- Visit `/examples/no-store` to see fresh data on every load
83+
- Refresh the page multiple times - timestamp changes each time
84+
- Compare with other caching strategies
85+
86+
### 4. Time-based Revalidation (`/examples/time-based-revalidation`)
87+
88+
Shows fetch with time-based revalidation (standalone, without tags).
89+
90+
**Features:**
91+
92+
- Automatic revalidation after specified time (30 seconds)
93+
- Balances freshness with performance
94+
- Standalone example of `next.revalidate`
95+
96+
**Try it:**
97+
98+
- Visit `/examples/time-based-revalidation` to see cached data
99+
- Refresh within 30 seconds - timestamp stays the same
100+
- Wait 30+ seconds and refresh - timestamp updates
101+
102+
### 5. Fetch with Tags (`/examples/fetch-tags`)
103+
104+
Demonstrates fetch caching with tags and time-based revalidation.
105+
106+
**Features:**
107+
108+
- Time-based revalidation (24 hours)
109+
- Cache tags for selective invalidation
110+
- Clear cache button to test tag revalidation
111+
- Shows character data from Futurama API
112+
- Displays cache information and rendered timestamp
113+
114+
**Try it:**
115+
116+
- Visit `/examples/fetch-tags` to see cached data
117+
- Click "Clear Cache" to invalidate the cache
118+
- Reload the page to see fresh data
119+
120+
### 6. unstable_cache (`/examples/unstable-cache`)
121+
122+
Demonstrates persistent caching with `unstable_cache` for function results.
123+
124+
**Features:**
125+
126+
- Cache any function, not just fetch requests
127+
- Tags and revalidation support
128+
- Side-by-side comparison with fetch caching
129+
- Perfect for database queries and computations
130+
- Shows when to use unstable_cache vs fetch
131+
132+
**Try it:**
133+
134+
- Visit `/examples/unstable-cache` to see both caching methods
135+
- Compare the timestamps and behavior
136+
- Click "Clear Tag Cache" to invalidate both caches
137+
- Understand when to use unstable_cache vs fetch
138+
139+
### 7. revalidateTag() with cacheLife (`/examples/revalidate-tag-cachelife`)
140+
141+
Demonstrates the updated `revalidateTag()` API in Next.js 16 with cacheLife profiles.
142+
143+
**Features:**
144+
145+
- Breaking change from Next.js 15 (cacheLife now required)
146+
- Different cacheLife profiles: 'max', 'hours', 'days'
147+
- Stale-while-revalidate behavior
148+
- Examples for each profile type
149+
- Code examples showing migration from Next.js 15
150+
151+
**Try it:**
152+
153+
- Visit `/examples/revalidate-tag-cachelife` to see all three profiles
154+
- Click "Revalidate" buttons to test each profile
155+
- Compare the behavior of different cacheLife profiles
156+
- See code examples for Next.js 15 vs Next.js 16
157+
158+
### 8. ISR with Static Params (`/examples/isr/blog/[id]`)
159+
160+
Incremental Static Regeneration with `generateStaticParams`.
161+
162+
**Features:**
163+
164+
- Static generation at build time
165+
- On-demand regeneration
166+
- Time-based revalidation (1 hour)
167+
- Multiple blog post routes
168+
169+
**Try it:**
170+
171+
- Visit `/examples/isr/blog/1` for the first post
172+
- Try different IDs like `/examples/isr/blog/2`, `/examples/isr/blog/3`
173+
- Check the rendered timestamp to see caching in action
174+
175+
### 9. Static Params Test (`/examples/static-params/[testName]`)
176+
177+
Tests static params generation with dynamic routes.
178+
179+
**Features:**
180+
181+
- Static params generation
182+
- Dynamic params support
183+
- Short revalidation period (5 seconds) for testing
184+
- Shows generation type (static vs dynamic)
185+
186+
**Try it:**
187+
188+
- Visit `/examples/static-params/cache` (pre-generated)
189+
- Try `/examples/static-params/test1` or `/examples/static-params/test2` (on-demand)
190+
191+
## API Routes
192+
193+
### Cache Revalidation (`/api/revalidate`)
194+
195+
Unified endpoint for revalidating cache by tag or path.
196+
197+
**Usage:**
198+
199+
**Tag-based revalidation (GET):**
200+
201+
- `GET /api/revalidate?tag=futurama` - Revalidates cache for the "futurama" tag with 'max' profile
202+
- `GET /api/revalidate?tag=futurama&cacheLife=hours` - Revalidates with 'hours' profile
203+
- `GET /api/revalidate?tag=futurama&cacheLife=days` - Revalidates with 'days' profile
204+
205+
**Tag-based revalidation (POST):**
206+
207+
- `POST /api/revalidate` with body `{ "tag": "futurama" }` - Revalidates cache for a tag (defaults to 'max')
208+
- `POST /api/revalidate` with body `{ "tag": "futurama", "cacheLife": "hours" }` - Revalidates with specific profile
209+
210+
**Path-based revalidation (POST):**
211+
212+
- `POST /api/revalidate` with body `{ "path": "/examples/default-cache" }` - Revalidates cache for a specific path
213+
214+
**Examples:**
215+
216+
```bash
217+
# Revalidate by tag (GET) - defaults to 'max' profile
218+
curl http://localhost:3000/api/revalidate?tag=futurama
219+
220+
# Revalidate by tag with specific profile (GET)
221+
curl http://localhost:3000/api/revalidate?tag=futurama&cacheLife=hours
222+
223+
# Revalidate by tag (POST) - defaults to 'max' profile
224+
curl -X POST http://localhost:3000/api/revalidate \
225+
-H "Content-Type: application/json" \
226+
-d '{"tag": "futurama"}'
227+
228+
# Revalidate by tag with specific profile (POST)
229+
curl -X POST http://localhost:3000/api/revalidate \
230+
-H "Content-Type: application/json" \
231+
-d '{"tag": "futurama", "cacheLife": "days"}'
232+
233+
# Revalidate by path (POST)
234+
curl -X POST http://localhost:3000/api/revalidate \
235+
-H "Content-Type: application/json" \
236+
-d '{"path": "/examples/default-cache"}'
237+
```
238+
239+
## Cache Handler
240+
241+
This example uses a custom Redis cache handler configured in `cache-handler.mjs`. The handler supports:
242+
243+
- Redis string-based caching
244+
- Local LRU fallback
245+
- Composite caching strategy
246+
- Tag-based cache invalidation
247+
248+
**Note:** The cache handler only works in production mode. In development mode, Next.js bypasses the cache handler entirely. You'll see a warning message in the console: `"Next.js does not use the cache in development mode. Use production mode to enable caching."`
38249

39-
## Clear fetch example cache
250+
## Technologies
40251

41-
- http://localhost:3000/api/cache
252+
- Next.js 16
253+
- React 19
254+
- TypeScript
255+
- Tailwind CSS
256+
- Redis
257+
- @fortedigital/nextjs-cache-handler
Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
import { dirname } from "path";
2-
import { fileURLToPath } from "url";
3-
import { FlatCompat } from "@eslint/eslintrc";
4-
5-
const __filename = fileURLToPath(import.meta.url);
6-
const __dirname = dirname(__filename);
7-
8-
const compat = new FlatCompat({
9-
baseDirectory: __dirname,
10-
});
1+
import nextCoreWebVitals from "eslint-config-next/core-web-vitals";
2+
import nextTypescript from "eslint-config-next/typescript";
113

124
const eslintConfig = [
13-
...compat.extends("next/core-web-vitals", "next/typescript"),
5+
...nextCoreWebVitals,
6+
...nextTypescript,
7+
{
8+
ignores: [
9+
"node_modules/**",
10+
".next/**",
11+
"out/**",
12+
"build/**",
13+
"next-env.d.ts",
14+
],
15+
},
1416
];
1517

1618
export default eslintConfig;

examples/redis-minimal/next.config.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@ import type { NextConfig } from "next";
33
const nextConfig: NextConfig = {
44
cacheHandler: require.resolve("./cache-handler.mjs"),
55
cacheMaxMemorySize: 0, // disable default in-memory caching
6-
experimental: {
7-
//ppr: "incremental",
8-
},
96
};
107

118
export default nextConfig;

examples/redis-minimal/package.json

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,28 @@
1010
"dev": "next dev --turbopack",
1111
"build": "next build",
1212
"start": "next start",
13-
"lint": "next lint"
13+
"lint": "eslint ."
1414
},
1515
"dependencies": {
1616
"@fortedigital/nextjs-cache-handler": "workspace:*",
17-
"ioredis": "^5.8.2",
18-
"next": "^15.5.6",
19-
"react": "^19.2.3",
20-
"react-dom": "^19.2.3",
17+
"ioredis": "^5.9.3",
18+
"next": "16.1.6",
19+
"react": "19.2.4",
20+
"react-dom": "19.2.4",
2121
"redis": "^5.10.0"
2222
},
2323
"devDependencies": {
24-
"@eslint/eslintrc": "^3",
2524
"@tailwindcss/postcss": "^4",
26-
"@types/node": "^24",
27-
"@types/react": "^19",
28-
"@types/react-dom": "^19",
25+
"@types/node": "^25",
26+
"@types/react": "19.2.14",
27+
"@types/react-dom": "19.2.3",
2928
"eslint": "^9",
30-
"eslint-config-next": "15.5.6",
29+
"eslint-config-next": "16.1.6",
3130
"tailwindcss": "^4",
3231
"typescript": "^5"
32+
},
33+
"overrides": {
34+
"@types/react": "19.2.14",
35+
"@types/react-dom": "19.2.3"
3336
}
3437
}

examples/redis-minimal/src/app/api/cache/route.ts

Lines changed: 0 additions & 6 deletions
This file was deleted.

0 commit comments

Comments
 (0)