Revalidation และ Cache Invalidation
ไอเดียในหนึ่งประโยค
หัวข้อที่มีชื่อว่า “ไอเดียในหนึ่งประโยค”เมื่อ data อยู่ใน Data Cache แล้ว เรา invalidate ได้สองทาง time-based (ปล่อยให้ stale หลัง N วินาที) หรือ on-demand (revalidateTag / revalidatePath หลัง mutation) และทั้งคู่ยัง refresh Full Route Cache ของ route ที่เกี่ยวข้องด้วย
Time-based revalidation
หัวข้อที่มีชื่อว่า “Time-based revalidation”ตั้ง lifetime ให้ fetch ที่ cache ไว้ด้วย next: { revalidate: N } หรือตั้งทั้ง route segment ด้วย export const revalidate เมื่อผ่านช่วงเวลานั้น request ถัดไปจะ trigger การ refresh แบบ background
// Per fetch: this data is at most 60 seconds staleawait fetch('https://api.example.com/posts', { next: { revalidate: 60 } })// app/blog/page.tsx — revalidate the entire segment every hourexport const revalidate = 3600On-demand revalidation ด้วย tag
หัวข้อที่มีชื่อว่า “On-demand revalidation ด้วย tag”สำหรับ data ที่เปลี่ยนตาม event ไม่ใช่ตามนาฬิกา ให้ tag fetch ไว้ แล้วเรียก revalidateTag หลัง mutation ทุก fetch ที่ถือ tag นั้นจะถูกทิ้งจาก Data Cache
export async function getPosts() { const res = await fetch('https://api.example.com/posts', { next: { tags: ['posts'] }, }) return res.json()}'use server'import { revalidateTag } from 'next/cache'
export async function createPost(formData: FormData) { await fetch('https://api.example.com/posts', { method: 'POST', body: JSON.stringify({ title: formData.get('title') }), }) // Invalidate every fetch tagged 'posts' revalidateTag('posts')}revalidatePath vs. revalidateTag
หัวข้อที่มีชื่อว่า “revalidatePath vs. revalidateTag”ทั้งคู่รันใน Server Action หรือ Route Handler revalidateTag เล็งไปที่ data ตาม tag ไม่ว่า fetch จากที่ไหน revalidatePath เล็งไปที่ route และเคลียร์ทุกอย่างที่ cache ไว้ให้ route นั้น ใช้ตอนที่เราไม่รู้ tag
'use server'import { revalidatePath } from 'next/cache'
export async function updateProfile() { // Re-render and refetch everything for this exact route revalidatePath('/profile')}map ลงบนสอง server cache
หัวข้อที่มีชื่อว่า “map ลงบนสอง server cache”revalidation แตะสองในสี่ชั้น เริ่มจากทิ้ง entry ที่ match จาก Data Cache และเพราะผล render ของ route ขึ้นกับ data นั้น จึง mark Full Route Cache ที่เกี่ยวข้องให้ stale ด้วย request ถัดไปจะ render ใหม่ด้วย data สดและเติมทั้งสอง cache กลับ ส่วน Request Memoization และ Router Cache ฝั่ง client ไม่ถูกแตะ Router Cache จะ refresh เองหลัง Server Action
flowchart LR
A["Server Action: mutate"] --> B["revalidateTag('posts')"]
B --> C["Data Cache: drop tagged entries"]
C --> D["Full Route Cache: mark routes stale"]
D --> E["Next request re-renders with fresh data"]