Asset pipeline · Dağıtım & varlık ömrü
Manifest & Yükleme Önceliği: Kritik Yol ve Lazy
Tüm asset'ler aynı anda inmemeli. Manifest hangi dosyanın ne zaman yükleneceğini söyler — ilk kare, etkileşim ve arka plan yükü ayrılır.
Loader yüzeyi üretim izleğinde, CDN header politikası önceki yaprakta kuruldu. Burada bu ikisinin üzerine bir zaman çizelgesi eklenir: hangi asset'in saniye sıfırda, hangisinin ilk etkileşimden önce, hangisinin boşta kalan zamanda indirileceği.
Bant genişliği sınırlıdır ve kullanıcının dikkati de öyle. 20 MB'lık bir kahraman modeliyle 20 MB'lık arka plan dekorunu aynı anda indirmek, ikisinin de yarım saniyede gelmesini beklemek kadar anlamsızdır — ilk kare için gerekli olan öncelik kazanmalı, gerisi beklemelidir.
Sayfayı bitirdiğinizde şu cümleyi kurabilmelisiniz: «Manifest bir dosya listesi değil bir zaman çizelgesidir; P0/P1/P2 katmanları ilk kare, etkileşim ve arka planı ayırır; preload sadece gerçekten kritik yol için kullanılır; progressive yükleme düşük detaylı bir placeholder ile başlar.»
Bu sayfanın sınırı
Bu sayfa şunları anlatır:
- Manifest şeması ve öncelik katmanları
- Preload vs lazy vs idle yükleme
- Kritik yol (hero asset) ve progressive strateji
Bilinçli olarak dışarıda bırakılan konular:
- Framework Suspense/loading detayı → Framework R3F yükleme
- glTF şema → glTF format
- LOD seviyesi kararının kendisi → Platform LOD
Kısa ayrım: Bu sayfa «ne zaman iner» · Platform LOD «hangi detay seviyesi var» · R3F «UI'da nasıl beklenir».
Öncelik katmanları: P0 / P1 / P2
P0 ilk kare için zorunludur (sky, zemin, hero silüet). P1 etkileşim öncesi gereklidir (pick edilebilir mesh, UI texture). P2 arka planda, kullanıcı fark etmeden yüklenir (dekor, uzak LOD, ses). Katman yazılmazsa her şey fiilen P0 olur ve ilk anlamlı boyama süresi şişer.
Katmanlama kararı, «bu asset olmadan sahne boş görünür mü» sorusuna verilen cevaptır. Estetik olarak hoş ama işlevsel olmayan detaylar hemen P2'ye düşer; bu ayrım genelde tasarım ile mühendislik arasında bir müzakere gerektirir.
Preload ve idle yükleme
requestIdleCallback veya ilk kare sonrası kurulan bir kuyruk ile P2 asset'leri indirilir. <link rel="preload"> yalnızca gerçekten P0 için kullanılmalıdır — aşırı preload, tarayıcının bant genişliğini P0'dan çalar ve «her şeyi öncelikli yapmak, hiçbir şeyi öncelikli yapmamak» sonucunu doğurur.
requestIdleCallback tüm tarayıcılarda garanti değildir; bir setTimeout fallback'i veya ilk render sonrası mikro-görev kuyruğu güvenli bir alternatiftir.
Progressive: düşük LOD önce
Platform LOD kararıyla uyumlu çalışır: önce düşük poligonlu bir placeholder, tam model P1'de yerini alır. Kullanıcı boş bir sahne görmez; bu, format şemasıyla ilgili değil tamamen yükleme sırasıyla ilgili bir karardır.
Geçiş anı (placeholder'dan tam modele) ani bir "pop" hissi vermemelidir — kısa bir crossfade veya opaklık geçişi bu sıçramayı yumuşatır.
Manifest şeması: versiyon + öncelik + bağımlılık
Bir manifest en az şu alanları taşımalıdır: asset kimliği, çözümlenmiş URL (versiyon mührüyle), öncelik katmanı ve varsa bağımlılık (bir sahne setinin birden fazla dosyaya ihtiyacı olduğunda). Bağımlılık bilgisi olmadan «bu asset yüklendi» ile «bu sahne gösterilebilir» arasındaki fark kaybolur.
Şema küçük tutulmalıdır — her yeni alan, manifest'i üreten otomasyonun ve okuyan runtime kodun birlikte güncellenmesi gereken bir sözleşme değişikliğidir.
Route/sahne bazlı manifest bölme
Tek bir dev manifest, küçük projelerde yeterlidir; ama çok sahneli bir uygulamada her route'un kendi manifest parçasına sahip olması, kullanıcının hiç ziyaret etmediği bir sahnenin asset listesini indirmesini önler. Ana manifest, alt manifest'lere işaret eden hafif bir dizin haline gelir.
Bu bölme, kod bölme (code splitting) ile aynı motivasyonu taşır: yalnızca gerekli olan indirilsin.
Kullanıcı etkileşimine göre öncelik değişimi
Statik P0/P1/P2 ataması bir başlangıç noktasıdır; bazı projelerde öncelik kullanıcı davranışına göre dinamik olarak değişir — örneğin bir envanter öğesinin üzerine gelindiğinde (hover) o öğenin yüksek detaylı versiyonu erken tetiklenebilir.
Bu dinamik önceliklendirme dikkatli kullanılmalıdır: her hover'da yeni bir yükleme tetiklemek, gereksiz ağ trafiği ve iptal edilen isteklerle sonuçlanabilir; bir debounce veya niyet tahmini (belirli bir süre hover kalması) makul bir denge sağlar.
Bant genişliği farkındalığı
Tarayıcının navigator.connection (Network Information API) desteği varsa, bağlantı tipi veya tahmini hız bilgisiyle P2 yüklemesi ertelenebilir veya daha düşük detaylı bir varyant seçilebilir. Bu API her tarayıcıda yoktur; yokluğunda varsayılan (orta) profile düşülmelidir.
Bant genişliği farkındalığı bir «her zaman doğru tahmin» aracı değildir — kaba bir sinyal olarak, aşırı yükleme riskini azaltan bir güvenlik önlemi olarak görülmelidir.
Yanlış öncelik kalıpları
- 20 MB hero + 20 MB dekor aynı anda indirilir
- Preload her dosya için körü körüne uygulanır
- Manifest yok, URL'ler koda dağınık şekilde gömülü
- P2'yi etkileşim öncesi zorunlu sanmak
- Hover'da sınırsız yükleme tetiklenir, debounce yok
- Bağlantı hızı hiç dikkate alınmaz
Simüle: öncelik kuyruğu
{
"stages": [
{ "priority": "P0", "assets": ["env/sky.glb", "env/ground_lod0.glb"] },
{ "priority": "P1", "assets": ["characters/hero-scan.a8f3c2.glb"] },
{ "priority": "P2", "assets": ["decor/props_pack.glb"], "idle": true }
]
}
function isSlowConnection() {
const c = navigator.connection
if (!c) return false
return c.saveData || /2g/.test(c.effectiveType || '')
}
export async function runLoadStages(stages, loadOne) {
for (const stage of stages) {
if (stage.idle) {
if (isSlowConnection() && stage.priority === 'P2') continue // yavas baglantida P2 atlanir
await new Promise((r) => requestIdleCallback ? requestIdleCallback(r) : setTimeout(r, 200))
}
await Promise.all(stage.assets.map((id) => loadOne(id)))
}
}
Üç öncelik profili
-
01 · Öncelik
Vitrin (az asset)
- P0
- Tek hero model
- P2
- Yok denecek kadar az
- Risk
- Gereğinden fazla preload
-
02 · Öncelik
Oyun seviyesi (orta)
- P0
- Zemin + karakter
- P1
- Etkileşimli objeler
- Risk
- P1/P2 sınırı bulanık
-
03 · Öncelik
Açık dünya (çok asset)
- Manifest
- Route bazlı bölünmüş
- P2
- Bant genişliği duyarlı
- Risk
- Bağımlılık takibi karmaşık
Holodepth perspektifleri
Manifest bir zaman çizelgesidir
«Dosya listesi» değil «zaman çizelgesi»dir; ilk saniye deneyimi büyük ölçüde burada kazanılır veya kaybedilir.
Öncelik, tahmin değil karardır
P0/P1/P2 ataması «muhtemelen önemli» değil «ilk kare için zorunlu mu» sorusuna verilen açık bir cevap olmalıdır.
Dinamik öncelik dikkatli kullanılır
Kullanıcı etkileşimine göre önceliklendirme güçlü bir araçtır ama debounce ve bant genişliği farkındalığı olmadan geri teper.
- Her asset bir öncelik katmanına atanmış mı?
- Preload yalnızca gerçek P0 için mi kullanılıyor?
- Progressive geçiş (placeholder → tam model) yumuşak mı?
- Manifest şeması bağımlılığı ifade edebiliyor mu?
- Çok sahneli projede manifest route bazlı bölünmüş mü?
- Hover/etkileşim tetiklemesi debounce'lu mu?
- Yavaş bağlantıda P2 otomatik ertelenebiliyor mu?
Holodepth içgörüsü
Öncelik planı oturunca sıradaki ve son yaprak: registry ve dispose ile ömür borusunun tamamlanması.
Sonraki kapı
Yükleme sırası netse varlık yönetimi yaprağında registry, LRU ve dispose tamamlanır.