deniz.in

Piyasalar

Hava durumu

Hava durumu yükleniyor

· kaynak dev.to (home feed)

Next.js App Router, kısmi bir dynamic segment nedeniyle 1.200 üretilmiş sayfayı sessizce atladı

Bir dev.to postmortem'i, factors-of-[number] adlı bir klasörün neden 1.200 sayfa yerine tek bir statik sayfa ürettiğini açıklıyor; çünkü App Router yalnızca tamamen köşeli parantezli segmentleri dynamic olarak değerlendiriyor.

Next.js App Router, kısmi bir dynamic segment nedeniyle 1.200 üretilmiş sayfayı sessizce atladı

Başarılı olup tek bir sayfa üreten bir build

Bir geliştirici, dev.to'da yayımladığı bir postmortem'de Next.js 16'daki App Router'ın bir yan projedeki 1.200 üretilmiş sayfayı sessizce nasıl yok saydığını anlatıyor. factorcalculator.org adlı site, herhangi bir sayının çarpanlarını, çarpan çiftlerini, asal çarpanlara ayırmasını ve bölenlerini gösteren bir matematik aracı; App Router, Tailwind ve static export ile oluşturulmuş ve Cloudflare Pages'e dağıtılmış. Altı hesaplayıcı sayfası elle yazılmış; kalan 1.200'ü /factors-of-1/'den /factors-of-1200/'a kadar uzanan üretilmiş route'lardı.

/factors-of-84/ gibi URL'ler elde etmek için yazar, route klasörüne factors-of-[number] adını verdi. Yazıya göre build herhangi bir hata veya uyarı vermeden tamamlandı ve tam olarak tek bir sayfa üretti: URL kodlamalı /factors-of-%5Bnumber%5D/ yolunda literal bir statik route. generateStaticParams fonksiyonu boş bir küme döndürmedi; hiç çalışmadı bile.

Bunun nedeni App Router'ın bir kuralı: bir path segmenti yalnızca segmentin tamamı köşeli parantez ifadesi olduğunda dynamic olur. [slug] dynamic'tir. factors-of-[number] ise yalnızca adında tesadüfen köşeli parantez bulunan bir klasördür; dolayısıyla router bu adı sıra dışı olan normal bir statik route olarak kaydeder. Router'ın bakış açısından uyarılacak bir şey yoktur.

Slug'u kendiniz ayrıştırmak

Çözüm, route'u app dizininin kökünde tek bir dynamic segmente ([slug]) indirmek ve öneki uygulama kodunda ayrıştırmaktı. Yazarın parser'ı, factors-of- önekini ve ardından rakamları içeren dizeleri kabul ediyor, baştaki sıfırları reddediyor ve sayının 1 ile 1200 arasında bir tam sayı olduğunu doğruluyor. generateStaticParams daha sonra 1.200 slug'ın tamamını önceden numaralandırıyor.

Yazıda dikkat çekmeye değer üç ayrıntı var:

  • Statik route'lar dynamic olanlara göre önceliklidir; dolayısıyla kök düzeyindeki bir [slug], bağımsız bir hesaplayıcı route'u gibi elle yazılmış sayfaları yutmaz; yalnızca statik route'ların eşleştirmediği istekleri alır.
  • dynamicParams değerini false yapmak, generateStaticParams dışındaki her şeyi 404'e çevirir. Bu ayar olmadan dynamic segment, sonlu ve bilinmesi amaçlanan URL uzayında rastgele URL'leri talep üzerine memnuniyetle render etmeye çalışırdı.
  • Baştaki sıfırlar reddediliyor ki /factors-of-012/, /factors-of-12/'nin bir kopyasını sunmasın. Yazarın deyişiyle bu koruma baştan eklemesi kolay, crawler'lar varyantları indeksledikten sonra telafi etmesi acı verici bir şeydir.

Sürekli geri dönen bir hydration uyuşmazlığı

İkinci sorun etkileşimli hesaplayıcıyla ilgiliydi: sunucuda render edilen ile istemcide render edilen HTML birbiriyle uyuşmuyordu. İlk suçlu locale'e bağlı biçimlendirmeydi; toLocaleString sunucuda "1,234" üretirken bazı tarayıcı locale'lerinde farklı bir basamak gruplaması üretebiliyor ve hydration sınırının iki tarafında iki farklı dizi ortaya çıkıyordu.

Belirleyici, regex tabanlı bir sayı biçimlendiricisi bu belirtiyi çözdü, ancak bileşen büyüdükçe uyuşmazlıklar başka yerlerde yeniden ortaya çıktı. Nihai çözüm yapısal oldu: sunucuda ve ilk istemci render'ında, ikisi bayt bayt aynı olacak şekilde statik bir iskelet render etmek, mount'tan sonra gerçek widget'ı yerleştirmek. Yazar bu ödünü kabul ediyor; JavaScript'i olmayan kullanıcılar ve crawler'lar aracı hiç görmüyor, ancak bunu kabul edilebilir buluyor, çünkü her sayfa sayfasındaki asıl içerik sunucuda render ediliyor.

Yazı ayrıca body öğesine öznitelik enjekte eden tarayıcı eklentilerini, suppressHydrationWarning ile susturulan yinelenen asılsız hydration uyarılarının kaynağı olarak gösteriyor.

Şablonlar yerine hesaplanan içerik

Üretilen sayfaların kendisi için yazar, şabran artı değişken metin ve dil modeli üretimi metinden kaçındı; arama motorlarının birbirine neredeyse aynı programatik sayfaları giderek daha fazla aşağı sıraladığına dikkat çekiyor. Bunun yerine her sayfanın içeriği, sayının gerçek matematiksel özelliklerinden hesaplanıyor: bölen sayısı, bölenler toplamı, asallık, mükemmel kare olup olmadığı, yüksek bileşik, üçgensel, Fibonacci sayısı ya da asal kuvvet olması ve bolluk sınıflandırması. Metinler bu özelliklere göre değişiyor; böylece mükemmel bir sayı, yüksek bileşik bir sayı ve mükemmel bir kare, kimse sayfaya özgü metin elle yazmadan farklı yorumlar alıyor.

Yol boyunca küçük bir kısıtlamayı da ortaya çıktı: kök layout, Metadata API aracılığıyla her başlığa bir sonek ekliyor ve arama sonuçları başlıkları 60 karakter civarında kesdiğinden, her sayfa başlığının yaklaşık 40 karakterlik bir işletme bütçesi var.

Son olarak yazar, kimsenin 1.200 sayfayı elle inceleyemeyeceği gerekçesiyle, her dağıtımdan önce build edilmiş çıktı dizinine karşı çalışan yaklaşık 200 satırlık doğrulama betiği yazdı.

Neden önemli

Buradaki arıza modu tehlikeli türden: temiz bir build, sağlıklı görünen bir dağıtım ve var olmayan 1.200 sayfa. Araç zincirindeki hiçbir şey "bir dynamic route oluşturdum" ile "adında köşeli parantez olan bir statik route oluşturdum" arasında ayrım yapmıyor; farkı yalnızca üretilen çıktıyı incelemek ortaya çıkarıyor. Yazı aynı zamanda App Router'daki sonlu programatik URL uzayları için yeniden kullanılabilir bir örüntü sunuyor: tek bir dynamic segment, kodda ayrıştırma, devre dışı dynamicParams ve yinelenen içerik varyantlarına karşı korumalar. Ve locale'e bağlı biçimlendirmenin, önceden render edilen her React uygulamasında güncel bir hydration tehlikesi olmaya devam ettiğinin bir hatırlatıcısı olarak da duruyor.

  • #next-js
  • #react
  • #hydration
  • #seo
  • #static-site-generation

İlgili yazılar