diff --git a/src/prompts/enable-cache-components-prompt.md b/src/prompts/enable-cache-components-prompt.md index e771fca..2607916 100644 --- a/src/prompts/enable-cache-components-prompt.md +++ b/src/prompts/enable-cache-components-prompt.md @@ -391,21 +391,30 @@ Search for Route Segment Config exports (these are DISABLED with Cache Component **Migration Map:** - `export const dynamic = 'force-static'` → Add `"use cache"` + cacheLife -- `export const dynamic = 'force-dynamic'` → Add `` boundary -- `export const revalidate = 3600` → Use `cacheLife('hours')` or custom profile +- `export const dynamic = 'force-dynamic'` → Add `` boundary (or nothing - dynamic is default) +- `export const revalidate = X` → Use matching `cacheLife()` profile (see table below) - `export const fetchCache = 'force-cache'` → Add `"use cache"` - `export const runtime = 'edge'` → Keep (still supported) - `export const runtime = 'nodejs'` → Remove (this is the default, no need to specify) - `export const dynamicParams = true` → Use `generateStaticParams` instead -**When removing exports, add migration comments:** +**Revalidate → cacheLife Mapping:** +| revalidate value | cacheLife equivalent | +|------------------|---------------------| +| `0` or `false` | Dynamic (no "use cache" needed) | +| `60` | `cacheLife('minutes')` | +| `3600` | `cacheLife('hours')` | +| `86400` | `cacheLife('days')` | +| `604800` | `cacheLife('weeks')` | +| Other values | `cacheLife({ revalidate: X })` | + +**When removing exports, add migration comments with the original value:** ```typescript -// MIGRATED: Was 'force-static' (export const dynamic) - now using "use cache" -// MIGRATED: Was 'force-dynamic' (export const dynamic) - now using -// MIGRATED: Was revalidate: 3600 - now using cacheLife('hours') +// MIGRATED from: export const revalidate = 60 +// → Add "use cache" + cacheLife('minutes') to maintain ~60s revalidation ``` -Document all locations now - you'll migrate them in Phase 5. +Document all locations now - you'll migrate them in Phase 3. **Step 6: Verify configuration changes** @@ -456,11 +465,58 @@ Make these changes FIRST, before running any build or dev server: grep -r "export const dynamic\|export const revalidate\|export const fetchCache" app/ ``` -For each file found, remove these exports and add migration comments: +For each file found, remove these exports and add migration comments with suggested cacheLife: + +**For `export const revalidate = X`:** + +Use this mapping to suggest the appropriate cacheLife based on the original value: + +| Original revalidate | Suggested cacheLife | Notes | +|---------------------|---------------------|-------| +| `revalidate = 0` (or `false`) | Dynamic (no cache) | Was already dynamic, no "use cache" needed | +| `revalidate = 1-59` | `cacheLife('seconds')` or custom | Very short cache, consider if caching helps | +| `revalidate = 60` | `cacheLife('minutes')` | revalidate: 60s | +| `revalidate = 61-3599` | `cacheLife({ revalidate: X })` | Custom value needed | +| `revalidate = 3600` | `cacheLife('hours')` | revalidate: 3600s (1 hour) | +| `revalidate = 3601-86399` | `cacheLife({ revalidate: X })` | Custom value needed | +| `revalidate = 86400` | `cacheLife('days')` | revalidate: 86400s (1 day) | +| `revalidate = 604800` | `cacheLife('weeks')` | revalidate: 604800s (1 week) | + +**Migration comment format - include the original value and suggestion:** +```typescript +// MIGRATED from: export const revalidate = 60 +// → Add "use cache" + cacheLife('minutes') to maintain ~60s revalidation +import { cacheLife } from 'next/cache' + +export default async function Page() { + "use cache" + cacheLife('minutes') // Replaces: export const revalidate = 60 + // ... +} +``` + +**For custom revalidate values (not matching a preset):** +```typescript +// MIGRATED from: export const revalidate = 1800 (30 minutes) +// → Add "use cache" + cacheLife({ revalidate: 1800 }) to maintain existing behavior +import { cacheLife } from 'next/cache' + +export default async function Page() { + "use cache" + cacheLife({ revalidate: 1800 }) // Replaces: export const revalidate = 1800 + // ... +} +``` + +**For `export const dynamic`:** +```typescript +// MIGRATED from: export const dynamic = 'force-static' +// → Add "use cache" to opt into caching (dynamic is now the default) +``` + ```typescript -// MIGRATED: Removed export const dynamic = 'force-static' (incompatible with Cache Components) -// MIGRATED: Removed export const revalidate = 3600 (incompatible with Cache Components) -// TODO: Will add "use cache" + cacheLife() after analyzing build errors +// MIGRATED from: export const dynamic = 'force-dynamic' +// → No change needed (dynamic is now the default), or wrap in for loading states ``` **Keep these exports if found:** @@ -1127,8 +1183,10 @@ Report findings in this format: ### Step 1: Obvious Breaking Changes Removed [x] Route Segment Config exports removed: [count] - - [file path]: Removed export const dynamic = 'force-static' - - [file path]: Removed export const revalidate = 3600 + - [file path]: Removed `export const dynamic = 'force-static'` → Added "use cache" + - [file path]: Removed `export const revalidate = 3600` → Added cacheLife('hours') + - [file path]: Removed `export const revalidate = 60` → Added cacheLife('minutes') + - [file path]: Removed `export const revalidate = 1800` → Added cacheLife({ revalidate: 1800 }) - ... [x] unstable_noStore() calls removed: [count] @@ -1220,6 +1278,12 @@ Report findings in this format: ### Summary of All Code Changes: - Total Route Segment Config exports removed: [count] + - `revalidate` exports migrated to cacheLife: [count] + - cacheLife('minutes'): [count] (was revalidate ≈ 60) + - cacheLife('hours'): [count] (was revalidate ≈ 3600) + - cacheLife('days'): [count] (was revalidate ≈ 86400) + - cacheLife({ revalidate: X }): [count] (custom values) + - `dynamic` exports removed: [count] - Total unstable_noStore() calls removed: [count] - Total Suspense boundaries added: [count] - Total "use cache" directives added: [count] diff --git a/src/resources/(nextjs16)/migration/nextjs-16-migration-examples.md b/src/resources/(nextjs16)/migration/nextjs-16-migration-examples.md index 442bdb8..f46c932 100644 --- a/src/resources/(nextjs16)/migration/nextjs-16-migration-examples.md +++ b/src/resources/(nextjs16)/migration/nextjs-16-migration-examples.md @@ -1429,7 +1429,20 @@ async function DynamicTimestamp() { ### Removing Route Segment Config -When enabling Cache Components, remove all Route Segment Config exports: +When enabling Cache Components, remove all Route Segment Config exports. **IMPORTANT:** Capture the original revalidate value and suggest the matching cacheLife profile. + +**Revalidate → cacheLife Mapping Table:** + +| Original revalidate | Suggested cacheLife | Profile timing | +|---------------------|---------------------|----------------| +| `0` or `false` | Dynamic (no "use cache") | Was already dynamic | +| `60` | `cacheLife('minutes')` | revalidate: 60s | +| `3600` | `cacheLife('hours')` | revalidate: 3600s (1 hour) | +| `86400` | `cacheLife('days')` | revalidate: 86400s (1 day) | +| `604800` | `cacheLife('weeks')` | revalidate: 604800s (1 week) | +| Other values | `cacheLife({ revalidate: X })` | Custom timing | + +**Example 1: Exact match (revalidate = 3600)** ```typescript // ❌ BEFORE - Route Segment Config (incompatible with Cache Components) @@ -1443,20 +1456,82 @@ export default async function Page() { } // ✅ AFTER - Cache Components approach -// MIGRATED: Removed export const dynamic = 'force-static' (incompatible with Cache Components) -// MIGRATED: Removed export const revalidate = 3600 (incompatible with Cache Components) -// MIGRATED: Removed export const fetchCache = 'force-cache' (incompatible with Cache Components) -// DECISION: Content changes hourly, cached for performance +// MIGRATED from: export const revalidate = 3600 +// → Using cacheLife('hours') to maintain ~1 hour revalidation import { cacheLife } from 'next/cache' export default async function Page() { - "use cache"; - cacheLife('hours'); // Equivalent to old revalidate: 3600 - + "use cache" + cacheLife('hours') // Replaces: export const revalidate = 3600 + const data = await fetch('https://api.example.com/data') return
{data}
} ``` +**Example 2: Custom value (revalidate = 1800)** + +```typescript +// ❌ BEFORE +export const revalidate = 1800 // 30 minutes + +export default async function Page() { + // ... +} + +// ✅ AFTER +// MIGRATED from: export const revalidate = 1800 (30 minutes) +// → Using cacheLife({ revalidate: 1800 }) to maintain exact timing +import { cacheLife } from 'next/cache' + +export default async function Page() { + "use cache" + cacheLife({ revalidate: 1800 }) // Replaces: export const revalidate = 1800 + // ... +} +``` + +**Example 3: Short revalidation (revalidate = 60)** + +```typescript +// ❌ BEFORE +export const revalidate = 60 // 1 minute + +export default async function Page() { + // ... +} + +// ✅ AFTER +// MIGRATED from: export const revalidate = 60 +// → Using cacheLife('minutes') to maintain ~60s revalidation +import { cacheLife } from 'next/cache' + +export default async function Page() { + "use cache" + cacheLife('minutes') // Replaces: export const revalidate = 60 + // ... +} +``` + +**Example 4: Dynamic content (revalidate = 0)** + +```typescript +// ❌ BEFORE +export const revalidate = 0 // Always dynamic + +export default async function Page() { + // ... +} + +// ✅ AFTER +// MIGRATED from: export const revalidate = 0 +// → No "use cache" needed - dynamic is now the default with Cache Components + +export default async function Page() { + // Dynamic by default - no changes needed + // ... +} +``` + ---