holodepth

Asset pipeline · Dağıtım & varlık ömrü

CDN & Statik Dağıtım: CORS, Header ve Edge

glTF ve texture dosyaları statik nesnedir; CDN ve cache header ilk kare süresini belirler. Bu sayfa cloud mimarisi değil, web Three projesinin dağıtım köprüsüdür.

Versiyon mührü önceki yapraktadır ve bu sayfanın ön koşuludur: hash'siz bir dosyaya agresif cache uygulamak, stale asset riskini büyütür. Burada header politikası ve CORS yüzeyi anlatılır — sunucu altyapısının kendisi (Terraform, bucket kurulumu) değil, tarayıcıya ulaşan sonucun ne olması gerektiği.

Bir web Three projesinde CDN, sadece «dosyaları hızlı sunan bir sunucu» değildir; hangi dosyanın ne kadar süre cache'te tutulacağına, hangi origin'lerin texture okuyabileceğine ve hangi coğrafi bölgeden hangi hızda yanıt geleceğine karar veren bir katmandır. Bu kararlar yanlış verildiğinde performans sorunları «kod yavaş» değil «dağıtım politikası yanlış» başlığı altında çözülür.

Sayfayı bitirdiğinizde şu cümleyi kurabilmelisiniz: «Statik asset'ler HTML/JS bundle'dan ayrı bir cache politikası ister; hash'li dosya immutable, manifest kısa ömürlü olmalı; cross-origin texture CORS'suz canvas'ı taint eder; tek CDN'lik projede bile fallback stratejisi düşünülmelidir.»

Bu sayfanın sınırı

Bu sayfa şunları anlatır:

  • Statik hosting + CDN köprüsü
  • Cache-Control stratejisi (kısa/uzun/immutable)
  • CORS ve cross-origin texture yüzeyi

Bilinçli olarak dışarıda bırakılan konular:

Kısa ayrım: Bu sayfa «tarayıcıya gelen header ve CORS» · Three.js CDN yaprağı «edge/deployment derinliği» · DevOps «altyapı kodu».

Statik nesne: GLB, bin, texture

Runtime asset'leri SSR gerektirmez; her istek için sunucuda yeniden hesaplanmaz, olduğu gibi edge'de cache'lenebilir. Holodepth: HTML/JS bundle ile asset CDN'ini ayır — ikisi farklı değişim sıklığına ve farklı cache politikasına sahiptir; aynı kural setiyle yönetmek, birini diğerine kurban eder.

Ayrım pratikte de fayda sağlar: asset bucket'ı farklı bir bölgeye veya farklı bir CDN sağlayıcısına taşınabilir, uygulama kodu deploy pipeline'ından bağımsız olarak asset güncellenebilir.

Header stratejisi: manifest vs hash dosya

manifest.json kısa max-age veya no-cache almalı; hash'li *.a8f3c2.glb dosyaları ise uzun max-age=31536000, immutable alabilir. Aynı header her dosyaya uygulanmamalıdır — bu, önceki yapraktaki versiyon mührünün doğrudan sonucu bir kuraldır.

Texture gibi orta sıklıkta değişen ama hash'siz sunulan dosyalarda orta uzunlukta bir max-age (örn. bir gün) makul bir orta yol olabilir; ideal olan her şeyin hash'lenmesidir ama küçük projelerde bu pragmatik bir ara adımdır.

CORS ve texture cross-origin

Texture başka bir origin'den geliyorsa crossOrigin = 'anonymous' ve CDN'de Access-Control-Allow-Origin başlığı gerekir; yoksa canvas taint olur ve toDataURL/readPixels gibi okuma işlemleri güvenlik hatasıyla başarısız olur — bu genelde ekran görüntüsü alma veya post-processing özelliklerinde fark edilir.

Aynı sorun HDR/EXR ortam haritalarında da görülür; CORS eksikse hata bazen sessiz kalır (texture siyah görünür) ve teşhisi zorlaşır. Holodepth: geliştirme ortamında bile prod CDN'e yakın bir CORS konfigürasyonu test edilmelidir.

Edge/bölgesel dağıtım ve ilk byte

Kullanıcıya coğrafi olarak yakın bir edge node'dan yanıt almak, büyük GLB dosyalarında saniyelerce fark oluşturabilir. CDN sağlayıcısı seçimi bu yaprağın konusu değildir, ama «asset'lerin edge'de cache'lendiğinden emin olma» — yani ilk isteğin cold cache mi warm cache mi olduğunu ölçme — burada önemlidir.

Cold cache (edge'de henüz yok) ile warm cache (edge'de zaten var) arasındaki fark, özellikle nadiren ziyaret edilen sayfalarda büyük olabilir; bu farkı bilmek, performans şikâyetlerini «kod» değil «cache ısınması» olarak doğru teşhis etmeye yardım eder.

Sıkıştırma katmanı: transfer vs içerik

İki farklı sıkıştırma katmanı birbirine karıştırılmamalıdır: transfer sıkıştırma (gzip/brotli, CDN tarafında otomatik) byte'ları ağda daha küçük taşır ama tarayıcıda açıldıktan sonra orijinal boyuta döner; içerik sıkıştırma (Draco/meshopt) geometri verisinin kendisini küçültür ve GPU'ya kadar küçük kalır.

glTF/GLB dosyaları genelde zaten sıkıştırılmış veri (binary buffer) içerir, bu yüzden gzip/brotli üzerine ek fayda azdır; ama JSON kısmı (manifest, .gltf metadata) metin sıkıştırmadan fayda görür. Draco kararının kendisi ayrı bir yaprakta derinleşir.

Fallback ve çok-CDN stratejisi

Tek CDN'e bağımlı bir proje, o CDN'in bölgesel bir kesintisinde tüm asset'lerini kaybeder. Küçük projeler için bu risk kabul edilebilir olabilir, ama kritik ürünlerde ikinci bir origin'e (yedek bucket) fallback URL'i manifest'te taşınabilir.

Fallback mantığı, loader hata sözleşmesiyle (üretim → runtime izleğinde ele alınan) birleşir: birincil CDN'den yükleme başarısız olursa ikinci URL denenir; bu davranış manifest verisiyle yönlendirilir, koda gömülü olmaz.

Ölçüm: TTFB ve cache hit oranı

Dağıtım kararlarının etkisini hissetmek yetmez, ölçmek gerekir. İki temel metrik: TTFB (ilk byte'a kadar geçen süre) ve cache hit oranı (isteklerin kaçının edge'den, kaçının origin'den karşılandığı). CDN sağlayıcısının panelinde bu ikisi genelde hazır gelir; yoksa Server-Timing veya özel header ile takip edilebilir.

Düşük cache hit oranı, genelde yanlış header stratejisinin (madde 2) belirtisidir; yüksek TTFB ise bölgesel dağıtımın (madde 4) yeniden gözden geçirilmesi gerektiğini gösterir.

Yanlış dağıtım kalıpları

  • Tüm dosyaya agresif no-cache (edge faydası tamamen kaybolur)
  • Hash'siz dosyaya immutable header (stale asset kalıcılaşır)
  • CORS unutulmuş HDR/texture (sessizce siyah görünen materyal)
  • Asset ve app aynı bucket'ta karışık cache politikası
  • Tek CDN'e tam bağımlılık, fallback planı yok
  • TTFB ve cache hit oranı hiç ölçülmemiş

Simüle: header eşlemesi ve CORS

{
  "rules": [
    { "match": "**/manifest.json", "cacheControl": "public, max-age=60" },
    { "match": "**/*.*.glb", "cacheControl": "public, max-age=31536000, immutable" },
    { "match": "**/textures/**", "cacheControl": "public, max-age=86400" }
  ],
  "fallbackOrigin": "https://backup-cdn.example.com"
}
import { TextureLoader } from 'three'

const loader = new TextureLoader()
loader.setCrossOrigin('anonymous')

export async function loadTexture(url, fallbackUrl) {
  try {
    return await loader.loadAsync(url)
  } catch (err) {
    if (!fallbackUrl) throw err
    return loader.loadAsync(fallbackUrl)
  }
}

Üç dağıtım profili

  • 01 · Dağıtım

    Tek CDN küçük proje

    Header
    Basit iki kural
    Fallback
    Yok
    Risk
    Tek kesinti noktası
  • 02 · Dağıtım

    Multi-region prod

    Header
    Kategori bazlı kural seti
    Fallback
    İkinci origin
    Risk
    Bölgesel cache tutarsızlığı
  • 03 · Dağıtım

    Kurumsal + private bucket

    Header
    İmzalı URL / kısa TTL
    CORS
    Kısıtlı origin listesi
    Risk
    Erişim politikası karmaşıklığı

Holodepth perspektifleri

CDN, versiyon mührünün icra alanıdır

Önceki yaprakta karar verilen hash/immutable ayrımı burada gerçek header'lara dönüşür; CDN hızı, yanlış cache ile «eski asset'i global ölçekte» dağıtır.

CORS bir güvenlik ayrıntısı değil, işlevsellik sınırıdır

Eksik CORS, çoğu zaman «çalışmıyor» değil «sessizce yanlış görünüyor» şeklinde ortaya çıkar — bu da onu daha tehlikeli yapar.

Ölçüm olmadan dağıtım kararı varsayımdır

TTFB ve cache hit oranı olmadan «CDN ekledik, hızlandı» cümlesi doğrulanamaz bir izlenimden ibarettir.

  1. App bundle ile asset CDN'i ayrı politika mı taşıyor?
  2. Hash'li dosyalar immutable, manifest kısa ömürlü mü?
  3. Cross-origin texture için CORS ve crossOrigin ayarı var mı?
  4. Bölgesel edge cache'in ısınma davranışı biliniyor mu?
  5. İçerik sıkıştırma (Draco) ile transfer sıkıştırma (gzip/brotli) karıştırılıyor mu?
  6. Fallback origin veya en azından bir hata stratejisi var mı?
  7. TTFB / cache hit oranı düzenli izleniyor mu?

Holodepth içgörüsü

Dağıtım yüzeyi hazırsa sıradaki yaprakta manifest ve yükleme önceliği ile hangi asset'in ilk saniyede ineceği planlanır.

Sonraki kapı

CDN politikası yazıldıysa manifest & yükleme önceliği ile hangi asset'in ilk saniyede ineceği belirlenir.