deniz.in

Piyasalar

Hava durumu

Hava durumu yükleniyor

· kaynak dev.to (home feed)

Vercel üzerindeki Next.js ISR sayfaları düşük trafiğe sahip rotalarda günlerce eski kalıyor

Bir dev.to yazısı, beş dakikalık revalidate değerine sahip Next.js sayfalarının Vercel üzerinde neden günlerce eski içerik sunabileceğini açıklıyor: ISR yeniden üretimi yalnızca bir istek geldiğinde çalışıyor.

Vercel üzerindeki Next.js ISR sayfaları düşük trafiğe sahip rotalarda günlerce eski kalıyor

Belirti

Vercel üzerinde Next.js tabanlı bir içerik sitesi işleten bir geliştirici — birkaç yüz sayfa, App Router, 300 saniyelik bir revalidate penceresi — bir detay sayfasındaki bir rakamı güncelledi ve bekledi. Beş dakika geçti; sayfa eski değerle yüklendi. Bir saat sonra hâlâ eski değerdi. Doğal sonuç ISR'nin bozulduğu yönünde. dev.to'da yayımlanan bir yazıya göre gerçek açıklama daha basit ve daha rahatsız edici: o sayfayı neredeyse hiç kimse ziyaret etmiyor ve Vercel üzerindeki ISR, önbelleğe alınmış bir sayfayı yalnızca bir istek geldiğinde yeniliyor.

Önce header'lardan teşhis koyun

Yazının merkezindeki hata ayıklama ipucu, tahmin etmeyi bırakıp HTTP yanıt header'larını okumak. Vercel üzerindeki herhangi bir Next.js sayfasına yapılan bir curl -I çağrısı, birlikte neredeyse her şeyi açıklayan dört değeri ortaya çıkarır:

  • x-nextjs-prerender: 1 — sayfa ön render edilmiş, dolayısıyla ISR semantiği geçerli. Bu header yoksa, rota dinamik olarak render ediliyordur ve gerisi alakasızdır.
  • x-nextjs-stale-time — saniye cinsinden yapılandırılmış revalidate değeri. Bu bir pencereyi tanımlar, bir takvimi değil.
  • x-vercel-cache — HIT, STALE veya MISS: edge'in taze bir kopya mı sunduğunu, yeniden üretimi başlatırken süresi geçmiş bir kopya mı sunduğunu yoksa origin'e mi başvurmak zorunda kaldığını.
  • age — önbelleğe alınmış girdinin kaç saniye önce oluşturulduğunu.

Yazarın örneğinde, stale-time değeri 300 saniye olan bir sayfa 529.343 — yani tam altı günden biraz fazla — age değeri bildiriyordu.

Yeniden üretim bir zamanlayıcıda değil, isteklerde çalışır

Next.js'te ya da Vercel'de rotalarınızı gezip süreleri doldukça yeniden inşa eden bir arka plan işi yoktur. İstek başına gerçekte şunlar olur:

  1. Edge, önbellek girdisinin yaşını stale-time ile karşılaştırır.
  2. Pencerenin içinde: önbelleğe alınmış kopyayı sun, bitti.
  3. Pencerenin dışında: eski kopyayı hemen sun ve arka planda bir yeniden üretim başlat.
  4. Bir süre sonraki bir sonraki istek, taze çıktıyı alan istektir.

İnsanları şaşırtan 3. adımdır: eskiliği keşfeden istek hâlâ eski içeriği alır — sadece sonraki gelenler için bir yeniden inşayı tetiklemenin bedelini öder.

Tek bir deployment üzerinde, hepsi aynı 300 saniyelik revalidate değerini paylaşan beş rota boyunca ölçülen sonuçlar:

Rota age x-vercel-cache
/ 64s HIT
/list 3.945s STALE
/index-page 3.945s STALE
/detail/one-item 529.343s STALE
/about 1.207.507s HIT

Anasayfa sürekli trafik aldığı için asla bir iki dakikadan daha eski olmuyor. Detay sayfası altı gün, hakkında sayfası ise yaklaşık on dört gün eski — yalnızca neredeyse hiç kimsenin onları istememesi nedeniyle. Yazının ifade ettiği gibi, revalidate: 300 "bu sayfa en fazla beş dakika eski" demek değildir — "birisi bu sayfayı önbelleğe alındıktan beş dakikadan fazla sonra istediğinde, yeniden inşayı başlat" demektir. Popüler bir rota için bu iki ifade fiilen aynı şeydir; uzun kuyrukta ise günlerce farklılık gösterir.

Nerede ısırır

Çoğu içerik için bu makul bir takas: yanıtlar hızlı kalır, origin yükü düşük kalır ve önemli sayfalar trafik onları yenilediği için taze kalır. Ziyaretçiler okudukları şeye göre hareket ettiğinde — fiyatlar, müsaitlik, puanlar, sıralamalar — bu makul olmaktan çıkar; altı günlük bir sayfa yalnızca güncel olmamakla kalmaz, yanıltıcıdır. Yazarın detay sayfaları değişen fiyat ve puanlar taşıdığı için, varsayılan beş dakikalık tazelik fiilen son ziyaretçi anındaki tazelikti.

Bir de deployment tuzağı var: bir düzeltme yayınlayın, sayfayı kontrol edin, eski sürümü görün ve deployment'ın başarısız olduğuna hükmedin. Başarısız olmadı — isteğiniz yeniden inşayı tetikledi ve değişiklik bir sonraki yüklemede görünüyor.

Bunun yerine ne yapmalı

Kontrol ettiğiniz veriler için on-demand revalidation kullanın. Temeldeki kayıt değiştiğinde, veriyi yazan her neyse — bir CMS webhook'u, bir admin işlemi, bir import script'i — Next.js'e açıkça haber verin:

js import { revalidatePath } from 'next/cache'

export async function POST(request: Request) { const { slug } = await request.() revalidatePath(/detail/${slug}) return Response.({ revalidated: true }) }

Tek bir değişiklik birden çok rotaya yayılıyorsa revalidateTag'i tercih edin: fetch'lere { next: { tags: ['catalogue'] } } ile etiket ekleyin ve veri değiştiğinde revalidateTag('catalogue') çağırın; bu, bağımlı her sayfayı aynı anda yeniden inşa eder.

Yazıdan iki ek öneri daha: revalidate değerini sadece küçültmeyin — 300'den 60'a düşürmek, kimsenin ziyaret etmediği bir sayfa için hiçbir şeyi değiştirmez ve zaten sorun olmayan sayfalara yalnızca yük ekler. Ve age header'ını izleyin: CI içinde ya da bir cron üzerinde önemli rotaları curl'leyip age, stale-time'ın bir katını aştığında uyarı veren küçük bir script, sorunu bir kullanıcı fark etmeden yakalar.

Neden önemli

ISR'nin tembel modeli bilinçli bir performans takasıdır, yine de revalidate'in hiçbir zaman vermediği bir tazelik garantisi olarak okunması kolaydır. Uzun bir sayfa kuyruğu artı kullanıcıların üzerinde hareket ettiği veriye sahip her App Router sitesi — e-ticaret, ilanlar, fiyat veya puan odaklı her şey — tazeliği olay güdümlü ele almalı ve revalidation'ı trafik beklemek yerine veri katmanından itmelidir. Ve önbelleğe alınmış bir sayfa yanlış göründüğünde, yanıt header'ları size saniyeler içinde bir önbellekleme sorununuz mu, bir trafik sorununuz mu yoksa bir deploy sorununuz mu olduğunu söyler.

  • #next-js
  • #vercel
  • #caching
  • #isr
  • #app-router

İlgili yazılar