Skip to content

Commit edd1acf

Browse files
authored
improve use cache migration (#108)
1 parent af3d601 commit edd1acf

2 files changed

Lines changed: 160 additions & 21 deletions

File tree

src/prompts/enable-cache-components-prompt.md

Lines changed: 77 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -391,21 +391,30 @@ Search for Route Segment Config exports (these are DISABLED with Cache Component
391391

392392
**Migration Map:**
393393
- `export const dynamic = 'force-static'` → Add `"use cache"` + cacheLife
394-
- `export const dynamic = 'force-dynamic'` → Add `<Suspense>` boundary
395-
- `export const revalidate = 3600` → Use `cacheLife('hours')` or custom profile
394+
- `export const dynamic = 'force-dynamic'` → Add `<Suspense>` boundary (or nothing - dynamic is default)
395+
- `export const revalidate = X` → Use matching `cacheLife()` profile (see table below)
396396
- `export const fetchCache = 'force-cache'` → Add `"use cache"`
397397
- `export const runtime = 'edge'` → Keep (still supported)
398398
- `export const runtime = 'nodejs'` → Remove (this is the default, no need to specify)
399399
- `export const dynamicParams = true` → Use `generateStaticParams` instead
400400

401-
**When removing exports, add migration comments:**
401+
**Revalidate → cacheLife Mapping:**
402+
| revalidate value | cacheLife equivalent |
403+
|------------------|---------------------|
404+
| `0` or `false` | Dynamic (no "use cache" needed) |
405+
| `60` | `cacheLife('minutes')` |
406+
| `3600` | `cacheLife('hours')` |
407+
| `86400` | `cacheLife('days')` |
408+
| `604800` | `cacheLife('weeks')` |
409+
| Other values | `cacheLife({ revalidate: X })` |
410+
411+
**When removing exports, add migration comments with the original value:**
402412
```typescript
403-
// MIGRATED: Was 'force-static' (export const dynamic) - now using "use cache"
404-
// MIGRATED: Was 'force-dynamic' (export const dynamic) - now using <Suspense>
405-
// MIGRATED: Was revalidate: 3600 - now using cacheLife('hours')
413+
// MIGRATED from: export const revalidate = 60
414+
// → Add "use cache" + cacheLife('minutes') to maintain ~60s revalidation
406415
```
407416

408-
Document all locations now - you'll migrate them in Phase 5.
417+
Document all locations now - you'll migrate them in Phase 3.
409418

410419
**Step 6: Verify configuration changes**
411420

@@ -456,11 +465,58 @@ Make these changes FIRST, before running any build or dev server:
456465
grep -r "export const dynamic\|export const revalidate\|export const fetchCache" app/
457466
```
458467

459-
For each file found, remove these exports and add migration comments:
468+
For each file found, remove these exports and add migration comments with suggested cacheLife:
469+
470+
**For `export const revalidate = X`:**
471+
472+
Use this mapping to suggest the appropriate cacheLife based on the original value:
473+
474+
| Original revalidate | Suggested cacheLife | Notes |
475+
|---------------------|---------------------|-------|
476+
| `revalidate = 0` (or `false`) | Dynamic (no cache) | Was already dynamic, no "use cache" needed |
477+
| `revalidate = 1-59` | `cacheLife('seconds')` or custom | Very short cache, consider if caching helps |
478+
| `revalidate = 60` | `cacheLife('minutes')` | revalidate: 60s |
479+
| `revalidate = 61-3599` | `cacheLife({ revalidate: X })` | Custom value needed |
480+
| `revalidate = 3600` | `cacheLife('hours')` | revalidate: 3600s (1 hour) |
481+
| `revalidate = 3601-86399` | `cacheLife({ revalidate: X })` | Custom value needed |
482+
| `revalidate = 86400` | `cacheLife('days')` | revalidate: 86400s (1 day) |
483+
| `revalidate = 604800` | `cacheLife('weeks')` | revalidate: 604800s (1 week) |
484+
485+
**Migration comment format - include the original value and suggestion:**
486+
```typescript
487+
// MIGRATED from: export const revalidate = 60
488+
// → Add "use cache" + cacheLife('minutes') to maintain ~60s revalidation
489+
import { cacheLife } from 'next/cache'
490+
491+
export default async function Page() {
492+
"use cache"
493+
cacheLife('minutes') // Replaces: export const revalidate = 60
494+
// ...
495+
}
496+
```
497+
498+
**For custom revalidate values (not matching a preset):**
499+
```typescript
500+
// MIGRATED from: export const revalidate = 1800 (30 minutes)
501+
// → Add "use cache" + cacheLife({ revalidate: 1800 }) to maintain existing behavior
502+
import { cacheLife } from 'next/cache'
503+
504+
export default async function Page() {
505+
"use cache"
506+
cacheLife({ revalidate: 1800 }) // Replaces: export const revalidate = 1800
507+
// ...
508+
}
509+
```
510+
511+
**For `export const dynamic`:**
512+
```typescript
513+
// MIGRATED from: export const dynamic = 'force-static'
514+
// → Add "use cache" to opt into caching (dynamic is now the default)
515+
```
516+
460517
```typescript
461-
// MIGRATED: Removed export const dynamic = 'force-static' (incompatible with Cache Components)
462-
// MIGRATED: Removed export const revalidate = 3600 (incompatible with Cache Components)
463-
// TODO: Will add "use cache" + cacheLife() after analyzing build errors
518+
// MIGRATED from: export const dynamic = 'force-dynamic'
519+
// → No change needed (dynamic is now the default), or wrap in <Suspense> for loading states
464520
```
465521

466522
**Keep these exports if found:**
@@ -1127,8 +1183,10 @@ Report findings in this format:
11271183
11281184
### Step 1: Obvious Breaking Changes Removed
11291185
[x] Route Segment Config exports removed: [count]
1130-
- [file path]: Removed export const dynamic = 'force-static'
1131-
- [file path]: Removed export const revalidate = 3600
1186+
- [file path]: Removed `export const dynamic = 'force-static'` → Added "use cache"
1187+
- [file path]: Removed `export const revalidate = 3600` → Added cacheLife('hours')
1188+
- [file path]: Removed `export const revalidate = 60` → Added cacheLife('minutes')
1189+
- [file path]: Removed `export const revalidate = 1800` → Added cacheLife({ revalidate: 1800 })
11321190
- ...
11331191
11341192
[x] unstable_noStore() calls removed: [count]
@@ -1220,6 +1278,12 @@ Report findings in this format:
12201278
12211279
### Summary of All Code Changes:
12221280
- Total Route Segment Config exports removed: [count]
1281+
- `revalidate` exports migrated to cacheLife: [count]
1282+
- cacheLife('minutes'): [count] (was revalidate ≈ 60)
1283+
- cacheLife('hours'): [count] (was revalidate ≈ 3600)
1284+
- cacheLife('days'): [count] (was revalidate ≈ 86400)
1285+
- cacheLife({ revalidate: X }): [count] (custom values)
1286+
- `dynamic` exports removed: [count]
12231287
- Total unstable_noStore() calls removed: [count]
12241288
- Total Suspense boundaries added: [count]
12251289
- Total "use cache" directives added: [count]

src/resources/(nextjs16)/migration/nextjs-16-migration-examples.md

Lines changed: 83 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,7 +1429,20 @@ async function DynamicTimestamp() {
14291429
14301430
### Removing Route Segment Config
14311431
1432-
When enabling Cache Components, remove all Route Segment Config exports:
1432+
When enabling Cache Components, remove all Route Segment Config exports. **IMPORTANT:** Capture the original revalidate value and suggest the matching cacheLife profile.
1433+
1434+
**Revalidate → cacheLife Mapping Table:**
1435+
1436+
| Original revalidate | Suggested cacheLife | Profile timing |
1437+
|---------------------|---------------------|----------------|
1438+
| `0` or `false` | Dynamic (no "use cache") | Was already dynamic |
1439+
| `60` | `cacheLife('minutes')` | revalidate: 60s |
1440+
| `3600` | `cacheLife('hours')` | revalidate: 3600s (1 hour) |
1441+
| `86400` | `cacheLife('days')` | revalidate: 86400s (1 day) |
1442+
| `604800` | `cacheLife('weeks')` | revalidate: 604800s (1 week) |
1443+
| Other values | `cacheLife({ revalidate: X })` | Custom timing |
1444+
1445+
**Example 1: Exact match (revalidate = 3600)**
14331446
14341447
```typescript
14351448
// ❌ BEFORE - Route Segment Config (incompatible with Cache Components)
@@ -1443,20 +1456,82 @@ export default async function Page() {
14431456
}
14441457

14451458
// ✅ AFTER - Cache Components approach
1446-
// MIGRATED: Removed export const dynamic = 'force-static' (incompatible with Cache Components)
1447-
// MIGRATED: Removed export const revalidate = 3600 (incompatible with Cache Components)
1448-
// MIGRATED: Removed export const fetchCache = 'force-cache' (incompatible with Cache Components)
1449-
// DECISION: Content changes hourly, cached for performance
1459+
// MIGRATED from: export const revalidate = 3600
1460+
// → Using cacheLife('hours') to maintain ~1 hour revalidation
14501461
import { cacheLife } from 'next/cache'
14511462

14521463
export default async function Page() {
1453-
"use cache";
1454-
cacheLife('hours'); // Equivalent to old revalidate: 3600
1455-
1464+
"use cache"
1465+
cacheLife('hours') // Replaces: export const revalidate = 3600
1466+
14561467
const data = await fetch('https://api.example.com/data')
14571468
return <div>{data}</div>
14581469
}
14591470
```
14601471
1472+
**Example 2: Custom value (revalidate = 1800)**
1473+
1474+
```typescript
1475+
// ❌ BEFORE
1476+
export const revalidate = 1800 // 30 minutes
1477+
1478+
export default async function Page() {
1479+
// ...
1480+
}
1481+
1482+
// ✅ AFTER
1483+
// MIGRATED from: export const revalidate = 1800 (30 minutes)
1484+
// → Using cacheLife({ revalidate: 1800 }) to maintain exact timing
1485+
import { cacheLife } from 'next/cache'
1486+
1487+
export default async function Page() {
1488+
"use cache"
1489+
cacheLife({ revalidate: 1800 }) // Replaces: export const revalidate = 1800
1490+
// ...
1491+
}
1492+
```
1493+
1494+
**Example 3: Short revalidation (revalidate = 60)**
1495+
1496+
```typescript
1497+
// ❌ BEFORE
1498+
export const revalidate = 60 // 1 minute
1499+
1500+
export default async function Page() {
1501+
// ...
1502+
}
1503+
1504+
// ✅ AFTER
1505+
// MIGRATED from: export const revalidate = 60
1506+
// → Using cacheLife('minutes') to maintain ~60s revalidation
1507+
import { cacheLife } from 'next/cache'
1508+
1509+
export default async function Page() {
1510+
"use cache"
1511+
cacheLife('minutes') // Replaces: export const revalidate = 60
1512+
// ...
1513+
}
1514+
```
1515+
1516+
**Example 4: Dynamic content (revalidate = 0)**
1517+
1518+
```typescript
1519+
// ❌ BEFORE
1520+
export const revalidate = 0 // Always dynamic
1521+
1522+
export default async function Page() {
1523+
// ...
1524+
}
1525+
1526+
// ✅ AFTER
1527+
// MIGRATED from: export const revalidate = 0
1528+
// → No "use cache" needed - dynamic is now the default with Cache Components
1529+
1530+
export default async function Page() {
1531+
// Dynamic by default - no changes needed
1532+
// ...
1533+
}
1534+
```
1535+
14611536
---
14621537

0 commit comments

Comments
 (0)