Files
Pulse ae39e45460 feat: biblioteca inteligente libs/ + 5 novas skills (20 skills total)
NOVAS SKILLS:
- next-best-practices      v0.1.0  (CLEAN) — Next.js App Router, RSC, caching, data
- nextjs-patterns          v1.0.0  (CLEAN) — Next.js 15: Server Actions, route handlers
- vite                     v1.0.0  (CLEAN) — env vars, aliases, proxy, CJS compat
- uncle-bob                v1.0.0  (CLEAN) — Clean Code, SOLID, Clean Architecture
- clean-code-review        v1.0.0  (CLEAN) — naming, guard clauses, anti-patterns, refactoring
- vue                      v1.0.0  (CLEAN) — Vue framework
- vue-composition-api-best-practices v1.0.0 (CLEAN) — composables, Pinia, reactivity

BIBLIOTECA INTELIGENTE libs/ (10 dominios, 11 arquivos):
- typescript/ — TS safe + generics gotchas
- react/ — Next.js App Router + Vite config
- vue/ — Composition API + Pinia
- linux/ — System diagnostic cheatsheet
- database/ — PostgreSQL + MySQL patterns
- browser/ — Chromium CLI + E2E testing
- security/ — SAST audit (OWASP Top 10)
- best-practices/ — Clean Code + SOLID + Clean Architecture
- deploy/ — Docker multi-stack + OpenClaw ops
- + INDEX.md como guia de navegacao

.learnings/ — LRN-20260519-003 criado (biblioteca compartilhada)
2026-05-19 21:03:25 -03:00

2.3 KiB

Next.js 15 Caching Deep Dive

The Four Caching Layers

1. Request Memoization (in-memory, per request)

Automatically deduplicates identical fetch() calls within a single render tree.

// Both components call fetchUser(id) — only ONE network request is made
async function Avatar({ id }) { const u = await fetchUser(id); return <img src={u.avatar} /> }
async function Name({ id }) { const u = await fetchUser(id); return <span>{u.name}</span> }

2. Data Cache (persistent, cross-request)

fetch() responses are stored on the server and reused across requests and deployments.

// Static — cached indefinitely
fetch(url)
fetch(url, { cache: "force-cache" })

// Time-based revalidation (ISR)
fetch(url, { next: { revalidate: 3600 } }) // revalidate every hour

// Always fresh — no caching
fetch(url, { cache: "no-store" })
fetch(url, { next: { revalidate: 0 } })

3. Full Route Cache (build-time static rendering)

Pages rendered at build time are stored as static HTML+RSC payload.

// Force dynamic rendering for this route
export const dynamic = "force-dynamic"

// Custom revalidation period for the whole route
export const revalidate = 60

4. Router Cache (client-side, per session)

Browser caches RSC payloads for instant back/forward navigation.

  • Static routes: cached for 5 minutes
  • Dynamic routes: cached for 30 seconds

On-Demand Revalidation

// Revalidate by path
import { revalidatePath } from "next/cache"
revalidatePath("/blog")
revalidatePath("/blog/[slug]", "page")

// Revalidate by cache tag
import { revalidateTag } from "next/cache"
revalidateTag("posts")

// Tagging fetches
fetch(url, { next: { tags: ["posts"] } })

unstable_cache for Non-Fetch Data

import { unstable_cache } from "next/cache"

const getCachedUser = unstable_cache(
  async (id: string) => db.user.findUnique({ where: { id } }),
  ["user"],
  { revalidate: 300, tags: ["users"] }
)

Common Pitfalls

Mistake Fix
Using fetch inside useEffect Move to Server Component or use React Query
Forgetting revalidatePath after mutations Call in Server Action after every write
Over-caching user-specific data Add cache: "no-store" or check cookies()/headers()
Sequential awaits Use Promise.all() for parallel fetching