Skip to content

Commit 31eb08f

Browse files
authored
Reworked example project (#160)
* Reworked examples * Updated readme * F
1 parent 6ca1d0b commit 31eb08f

File tree

19 files changed

+898
-181
lines changed

19 files changed

+898
-181
lines changed

examples/redis-minimal/README.md

Lines changed: 109 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,130 @@
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 build # important to run once to create cacheHandler dist file
10-
npm run dev
1111
```
1212

13-
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**:
1418

1519
```bash
16-
npm i
1720
npm run build
1821
npm run start
1922
```
2023

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

23-
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.
2435

2536
## Examples
2637

27-
- http://localhost:3000
28-
- http://localhost:3000/fetch-example
29-
- http://localhost:3000/static-params-test/cache
38+
The application includes several examples demonstrating different Next.js caching features:
39+
40+
### 1. Home Page (`/`)
41+
42+
Overview page listing all available examples with descriptions and features.
43+
44+
### 2. Fetch with Tags (`/examples/fetch-tags`)
45+
46+
Demonstrates fetch caching with tags and time-based revalidation.
47+
48+
**Features:**
49+
50+
- Time-based revalidation (24 hours)
51+
- Cache tags for selective invalidation
52+
- Clear cache button to test tag revalidation
53+
- Shows character data from Futurama API
54+
- Displays cache information and rendered timestamp
55+
56+
**Try it:**
57+
58+
- Visit `/examples/fetch-tags` to see cached data
59+
- Click "Clear Cache" to invalidate the cache
60+
- Reload the page to see fresh data
61+
62+
### 3. ISR with Static Params (`/examples/isr/blog/[id]`)
63+
64+
Incremental Static Regeneration with `generateStaticParams`.
65+
66+
**Features:**
67+
68+
- Static generation at build time
69+
- On-demand regeneration
70+
- Time-based revalidation (1 hour)
71+
- Multiple blog post routes
72+
73+
**Try it:**
74+
75+
- Visit `/examples/isr/blog/1` for the first post
76+
- Try different IDs like `/examples/isr/blog/2`, `/examples/isr/blog/3`
77+
- Check the rendered timestamp to see caching in action
78+
79+
### 5. Static Params Test (`/examples/static-params/[testName]`)
80+
81+
Tests static params generation with dynamic routes.
82+
83+
**Features:**
84+
85+
- Static params generation
86+
- Dynamic params support
87+
- Short revalidation period (5 seconds) for testing
88+
- Shows generation type (static vs dynamic)
89+
90+
**Try it:**
91+
92+
- Visit `/examples/static-params/cache` (pre-generated)
93+
- Try `/examples/static-params/test1` or `/examples/static-params/test2` (on-demand)
94+
95+
## API Routes
96+
97+
### Clear Cache (`/api/cache`)
98+
99+
Clears cache for a specific tag.
100+
101+
**Usage:**
102+
103+
- `GET /api/cache?tag=futurama` - Clears cache for the "futurama" tag
104+
- Default tag is "futurama" if not specified
105+
106+
**Example:**
107+
108+
```bash
109+
curl http://localhost:3000/api/cache?tag=futurama
110+
```
111+
112+
## Cache Handler
113+
114+
This example uses a custom Redis cache handler configured in `cache-handler.mjs`. The handler supports:
115+
116+
- Redis string-based caching
117+
- Local LRU fallback
118+
- Composite caching strategy
119+
- Tag-based cache invalidation
120+
121+
**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."`
30122

31-
## Clear fetch example cache
123+
## Technologies
32124

33-
- http://localhost:3000/api/cache
125+
- Next.js 16
126+
- React 19
127+
- TypeScript
128+
- Tailwind CSS
129+
- Redis
130+
- @fortedigital/nextjs-cache-handler
Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
import { revalidateTag } from "next/cache";
2+
import { NextRequest } from "next/server";
23

3-
export async function GET() {
4-
revalidateTag("futurama", "max");
5-
return new Response("Cache cleared for futurama tag");
4+
export async function GET(request: NextRequest) {
5+
const searchParams = request.nextUrl.searchParams;
6+
const tag = searchParams.get("tag") || "futurama";
7+
8+
try {
9+
revalidateTag(tag, "max");
10+
return new Response(`Cache cleared for tag: ${tag}`, {
11+
status: 200,
12+
});
13+
} catch (error) {
14+
return new Response(`Error clearing cache for tag: ${tag}`, {
15+
status: 500,
16+
});
17+
}
618
}
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import { ExampleLayout } from "@/components/ExampleLayout";
2+
import { ClearCacheButton } from "@/components/ClearCacheButton";
3+
import { InfoCard } from "@/components/InfoCard";
4+
import { CodeBlock } from "@/components/CodeBlock";
5+
import { FuturamaCharacter } from "@/types/futurama";
6+
7+
export default async function FetchTagsExample() {
8+
let name: string;
9+
let character: FuturamaCharacter;
10+
const timestamp = new Date().toISOString();
11+
12+
try {
13+
const characterResponse = await fetch(
14+
"https://api.sampleapis.com/futurama/characters/1",
15+
{
16+
next: {
17+
revalidate: 86400,
18+
tags: ["futurama"],
19+
},
20+
}
21+
);
22+
character = await characterResponse.json();
23+
name = character.name.first;
24+
} catch (error) {
25+
console.error("Error fetching character data:", error);
26+
return (
27+
<ExampleLayout
28+
title="Fetch with Tags Example"
29+
description="Demonstrates fetch caching with tags and time-based revalidation"
30+
>
31+
<div className="text-red-600 dark:text-red-400">
32+
An error occurred during fetch. Please check your network connection.
33+
</div>
34+
</ExampleLayout>
35+
);
36+
}
37+
38+
return (
39+
<ExampleLayout
40+
title="Fetch with Tags Example"
41+
description="This example demonstrates fetch caching with tags and time-based revalidation. The data is cached for 24 hours and can be invalidated using the 'futurama' tag."
42+
actions={<ClearCacheButton tag="futurama" />}
43+
>
44+
<div className="space-y-6">
45+
<InfoCard title="How it works">
46+
<ul className="list-disc list-inside space-y-1">
47+
<li>
48+
Data is fetched with a 24-hour revalidation period (
49+
<code className="bg-gray-200 dark:bg-gray-800 px-1 rounded">
50+
revalidate: 86400
51+
</code>
52+
)
53+
</li>
54+
<li>
55+
Cache is tagged with{" "}
56+
<code className="bg-gray-200 dark:bg-gray-800 px-1 rounded">
57+
&quot;futurama&quot;
58+
</code>{" "}
59+
for selective invalidation
60+
</li>
61+
<li>
62+
Click &quot;Clear Cache&quot; to invalidate the cache and see
63+
fresh data on reload
64+
</li>
65+
<li>
66+
The timestamp shows when this page was rendered (cached pages will
67+
show the same timestamp)
68+
</li>
69+
</ul>
70+
</InfoCard>
71+
72+
<div className="space-y-4">
73+
<div>
74+
<h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100 mb-2">
75+
Character Data
76+
</h2>
77+
<div className="bg-gray-50 dark:bg-gray-900 rounded-lg p-4 space-y-2">
78+
<div>
79+
<span className="font-medium text-gray-700 dark:text-gray-300">
80+
Name:
81+
</span>{" "}
82+
<span className="text-gray-900 dark:text-gray-100">{name}</span>
83+
</div>
84+
{character.name.middle && (
85+
<div>
86+
<span className="font-medium text-gray-700 dark:text-gray-300">
87+
Middle Name:
88+
</span>{" "}
89+
<span className="text-gray-900 dark:text-gray-100">
90+
{character.name.middle}
91+
</span>
92+
</div>
93+
)}
94+
<div>
95+
<span className="font-medium text-gray-700 dark:text-gray-300">
96+
Last Name:
97+
</span>{" "}
98+
<span className="text-gray-900 dark:text-gray-100">
99+
{character.name.last}
100+
</span>
101+
</div>
102+
{character.occupation && (
103+
<div>
104+
<span className="font-medium text-gray-700 dark:text-gray-300">
105+
Occupation:
106+
</span>{" "}
107+
<span className="text-gray-900 dark:text-gray-100">
108+
{character.occupation}
109+
</span>
110+
</div>
111+
)}
112+
</div>
113+
</div>
114+
115+
<div>
116+
<h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100 mb-2">
117+
Cache Information
118+
</h2>
119+
<div className="bg-gray-50 dark:bg-gray-900 rounded-lg p-4">
120+
<div>
121+
<span className="font-medium text-gray-700 dark:text-gray-300">
122+
Rendered at:
123+
</span>{" "}
124+
<span className="text-gray-900 dark:text-gray-100 font-mono text-sm">
125+
{timestamp}
126+
</span>
127+
</div>
128+
<div className="mt-2">
129+
<span className="font-medium text-gray-700 dark:text-gray-300">
130+
Cache Tag:
131+
</span>{" "}
132+
<code className="bg-gray-200 dark:bg-gray-800 px-2 py-1 rounded text-sm">
133+
futurama
134+
</code>
135+
</div>
136+
<div className="mt-2">
137+
<span className="font-medium text-gray-700 dark:text-gray-300">
138+
Revalidation:
139+
</span>{" "}
140+
<span className="text-gray-900 dark:text-gray-100">
141+
24 hours
142+
</span>
143+
</div>
144+
</div>
145+
</div>
146+
</div>
147+
148+
<div>
149+
<h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100 mb-2">
150+
Code Example
151+
</h2>
152+
<CodeBlock>
153+
{`const response = await fetch(
154+
"https://api.sampleapis.com/futurama/characters/1",
155+
{
156+
next: {
157+
revalidate: 86400,
158+
tags: ["futurama"],
159+
},
160+
}
161+
);`}
162+
</CodeBlock>
163+
</div>
164+
</div>
165+
</ExampleLayout>
166+
);
167+
}
168+

0 commit comments

Comments
 (0)