Önbellekleme ve yeniden doğrulama
Rota segmenti yapılandırması, unstable_cache, revalidateTag / revalidatePath ve stale-while-revalidate.
Rota işleyicisi yanıtlarını ve verileri önbelleğe alın, ardından zamanlayıcıyla veya talep üzerine yeniden doğrulayın. Arka planda tek bir yenileme çalışırken güncelliğini yitirmiş girdiler hemen sunulur.
Rota işleyicileri
GET rota işleyicileri varsayılan olarak dinamiktir. Önbelleğe almayı rota segmenti yapılandırmasıyla etkinleştirin:
export const revalidate = 60;export async function GET() { const posts = await db.posts.latest(); return Response.json(posts);}| Dışa aktarım | Davranış |
|---|---|
| (yok) | Her istekte çalışır |
dynamic = "force-static" | Yeniden doğrulanana kadar önbelleğe alınır |
revalidate = N | Önbelleğe alınır; N saniye sonra güncelliğini yitirir |
revalidate = 0 veya dynamic = "force-dynamic" | Her istekte çalışır |
Diğer dynamic değerleri TX031 hatasıyla başarısız olur. Text.js bir işleyicinin isteği ne zaman okuduğunu algılayamadığı için Next.js’in "error" değeri de buna dahildir.
Önbelleğe alınan işleyicilerde her yol adı için bir girdi bulunur ve request derleme zamanındaki gibi görünür: sorgu dizesi, üstbilgiler, çerezler veya gövde içermez. Bunları dinamik bir işleyicide okuyun. Yalnızca GET ve HEAD önbelleğe alınır. 5xx durumu, Set-Cookie üstbilgisi veya Cache-Control: private / no-store içeren yanıtlar döndürülür ancak hiçbir zaman saklanmaz.
Üstbilgiler
Önbelleğe alınan yanıtlar şunları taşır:
| Üstbilgi | Değer |
|---|---|
x-textjs-cache | MISS, HIT veya STALE |
Cache-Control | s-maxage=N, stale-while-revalidate=<1 year − N> veya force-static için s-maxage=31536000 |
Ara katman istek için çerez ayarladığında, yeniden yazma yaptığında veya istek üstbilgilerini geçersiz kıldığında, üretilen üstbilgi private, no-cache, no-store, max-age=0, must-revalidate olur; böylece paylaşılan önbellekler ziyaretçiye özgü bir kararı hiçbir zaman tekrar sunmaz. İşleyicinin ayarladığı Cache-Control üstbilgisi korunur.
text dev komutunda segment yapılandırması uygulanır ancak hiçbir şey saklanmaz; bu nedenle her istek işleyiciyi çalıştırır.
Veri önbelleği
Herhangi bir asenkron fonksiyonu @textjs/app/cache paketindeki unstable_cache ile önbelleğe alın:
import { unstable_cache } from "@textjs/app/cache";export const getPosts = unstable_cache( async (author: string) => db.posts.byAuthor(author), ["posts"], { tags: ["posts"], revalidate: 300 },);Anahtar, değere göre kodlanmış anahtar parçaları ve argümanlardan oluşur (undefined ve null, Map, Set, Date ve URL argümanları birbirinden ayrı kalır). Anahtar parçaları yoksa fonksiyonu kaynak kodu ve oluşturulduğu yer tanımlar; fonksiyon dış kapsamındaki değerleri kullandığında, örneğin her istek için veya bir döngü içinde oluşturulduğunda, anahtar parçalarını iletin. Sonuçlar JSON olarak serileştirilir; bu nedenle her çağrı yeni bir kopya döndürür (ve Date nesneleri dize olarak geri döner); serileştirilemeyen bir sonuç hata fırlatır. cache(fn, { key, tags, revalidate }) aynı ayarları bir seçenekler nesnesi olarak alır.
Önbelleğe alınmış bir rota işleyicisinde veri girdileri, etiketlerini ve en kısa revalidate değerlerini rotaya aktarır: "posts" etiketini yeniden doğrulamak /api/posts yolunu da yeniler. revalidate: 0 içeren bir veri çağrısı rotayı dinamik hale getirir.
Yeniden doğrulama sırasında eski veriyi sunma
Bir girdinin yaşı revalidate değerini aştığında:
- Sonraki istek güncelliğini yitirmiş değeri hemen alır (
STALE). - Arka planda tek bir yenileme çalışır; eşzamanlı istekler bunu paylaşır.
- Yenileme hata fırlatırsa güncelliğini yitirmiş değer sunulmaya devam eder ve hata günlüğe kaydedilir.
Vercel ve Cloudflare’da arka plan yenilemeleri waitUntil() ile kaydedilir. Bir yıldan eski girdiler her zaman ön planda yeniden hesaplanır.
Talep üzerine yeniden doğrulama
import { revalidatePath, revalidateTag } from "@textjs/app/cache";export async function POST(request: Request) { // Anyone can POST here: require a secret shared with your CMS or webhook. if (request.headers.get("authorization") !== `Bearer ${process.env.REVALIDATE_SECRET}`) { return new Response("Unauthorized", { status: 401 }); } await revalidateTag("posts"); await revalidatePath("/api/feed"); return Response.json({ revalidated: true });}| Çağrı | Geçersiz kıldıkları |
|---|---|
revalidateTag("posts") | posts etiketli her şey; sonraki istekte yeniden hesaplanır |
revalidateTag("posts", "max") | Güncelliğini yitirmiş olarak işaretler; yenilenirken sonraki isteğe eski değer sunulur |
revalidatePath("/api/feed") | Belirtilen yol |
revalidatePath("/api/posts/[id]") | Dinamik bir rotanın tüm yolları |
revalidatePath("/api", "layout") | /api altındaki her şey |
İkisi de bir promise döndürür. Bellek içi depoda geçersiz kılma hemen gerçekleşir; özel depo asenkron olduğunda await ile bekleyin.
Özel önbellek depoları
Varsayılan depo, her sunucu örneği için bellek içi bir LRU’dur (1.000 girdi, yaklaşık 50 MB). Örnekler arasında önbellek paylaşmak için cacheHandler değerini, varsayılan dışa aktarımı bir CacheStore olan modüle yönlendirin:
export default defineConfig({ cacheHandler: "./cache-handler.ts" });import type { CacheStore } from "@textjs/app/cache";const store: CacheStore = { async get(key) { return redis.get(key).then((v) => (v ? JSON.parse(v) : undefined)); }, async set(key, entry) { await redis.set(key, JSON.stringify(entry)); }, async delete(key) { await redis.del(key); }, async markTags(tags, mode, at) { for (const t of tags) await redis.hset(`tag:${t}`, mode, at); }, async getTagState(tags) { /* max expiredAt / staleAt across tags */ return { expiredAt: 0, staleAt: 0 }; },};export default store;Girdiler düz JSON’dur. Alternatif olarak setCacheStore(store) çalışma zamanında bir depo kurar.
Platform notları
- Her sunucusuz örneğin (Vercel fonksiyonları, Cloudflare isolate’leri) kendi bellek içi önbelleği vardır.
Cache-Control: s-maxage, platform CDN’inin de yanıtları önbelleğe almasını sağlar; talep üzerine yeniden doğrulama CDN önbelleğini temizlemez.revalidateTagher örneğe ulaşmalıysa paylaşılan bircacheHandlerkullanın. - Cloudflare,
nodejs_compatbayrağını gerektirir (önbellekAsyncLocalStoragekullanır). Dağıtım bölümüne bakın.