Framework entegrasyonları · React Three Fiber
Yükleme & Suspense Köprüsü: Asenkron Kargo Diplomasisi
Canlı kare ağacı kurduktan sonra asıl risk çoğu zaman
henüz gelmemiş varlıktır. Bu sayfa R3F'de
useLoader, Suspense askısı ve dispose sahipliğini anlatır:
React Suspense temeli değil · Three ↔ React asenkron köprüsü.
Holodepth bu yaprağı «Suspense nedir?» dersi veya glTF JSON şema turu olarak yazmaz. React askı modeli React Vitae omurgasındadır. Dosya alanları, bufferView, PBR slot spekü format izleklerindedir. Sıkıştırma / LOD kalitesi Platform · Asset sıkıştırma & LOD yaprağındadır. Canvas kökü, deklaratif katalog ve useFrame önceki R3F yapraklarındadır.
Sayfayı bitirdiğinizde şu cümleyi kurabilmelisiniz: «useLoader URL + loader sınıfı kimliğidir. Suspense eksik kargoda ağacı askıya alır. Cache paylaşımı clone politikası ister. Dispose sahiplik sözleşmesidir. Hatalar sınır bileşenine düşer. Ağır decode kareye gömülmez. Sonraki kapı pointer & picking'tir.»
Bu sayfanın sınırı · komşu konularla ayrım
Bu sayfa R3F'de asenkron varlık köprüsünü anlatır:
useLoaderkimliği · Suspense askı semantiği- Cache / clone · fallback UX
- Hata yolu · dispose sahipliği
- Decode'u kareye gömmeme · üç yükleme profili
Bilinçli olarak dışarıda bırakılan konular:
- Canvas / frameloop / DPR → Canvas & kök sözleşme
- args / attach / primitive → Deklaratif sahne grafı
- useFrame / store → useFrame / useThree
- Pointer / raycast → Pointer olayları & picking
- Instancing / ağır kaçış → Performans & imperatif kaçış
- React Suspense 101 → React Vitae · glTF/GLB şema & DCC export → format / modelleme izlekleri · Draco/KTX2 derinliği → Platform asset
Kısa ayrım: Bu sayfa «kargo nasıl askıya alınıp sahiplenilir?» · Format «paket içinde ne var?» · Platform asset «boyut / LOD kalitesi» · useFrame «geldikten sonra karede kim iter?».
Asenkron kargo · senkron ağaç
Deklaratif mesh anında vardır; doku, buffer geometri veya model ise ağdan / diskten gelir. R3F köprüsü bu gecikmeyi React ağacının askı diline çevirir: çocuk hazır değilse üst sınır fallback gösterir, hazır olunca katalog düğümü yerleşir.
Imperatif Three'de çoğunlukla callback / Promise ile
scene.add edersiniz. R3F'de aynı işi «bileşen render
yolunda askıya düşen yük» olarak yazarsınız. Holodepth: API farkı
evrim değil; sahiplik ve hata yolunun nerede yazıldığı
farkıdır.
Ağaç senkron görünür; kargo asenkron gelir. Köprü ikisini yalanlamadan birleştirir.
useLoader: kimlik sözleşmesi
useLoader(LoaderClass, url) (ve çoklu URL varyantları)
yüklemeyi Fiber cache'ine bağlar. Holodepth kimlik kuralı:
aynı loader sınıfı + aynı URL = paylaşılan cache kaydı
adayıdır. URL'yi her render'da yeniden üretilmiş query ile
rastgeleleştirmek cache'i deler; bilinçli busting ise ürün kararıdır.
Loader sınıfı TextureLoader, AudioLoader veya model loader olabilir. Bu sayfa glTF alan listesini açmaz: model loader'ı «bir loader örneği» olarak kullanırız. Paket şeması, skin, animasyon sampler'ı format omurgasındadır.
extensions / DRACOLoader bağlama gibi kurulumlar Three asset borusuna aittir; R3F tarafında merak ettiğiniz soru: kurulum bir kez mi, her bileşende mi? Holodepth: loader eklentilerini uygulama ömründe tek yerde mühürleyin, çocuklara çoğaltmayın.
Suspense: trafik ışığı
Suspense temelini Vitae anlatır. R3F köprüsünde semantik şudur:
yükleyici henüz çözülmediyse alt ağaç «hazır değil» sinyalidir; en yakın
Suspense sınırı fallback gösterir. Holodepth ürün dilinde
fallback boş siyah kutu olmamalı: iskelet, düşük müsat / proxy mesh
veya DOM spinner (host'ta) bilinçli seçilir.
Sınır nerede? Tüm Canvas'ı tek Suspense'e sarmak kaba ama basit; her ürün parçasına ayrı sınır koymak progressive reveal verir, fakat layout zıplaması üretebilir. Profil seçin (§10).
Askı sırasında useFrame abonelikleri o alt ağaçta yoktur (ağaç
yoksa). Demand kökte ise yük bitince
invalidate gerekebilir; kare sayfasındaki köprüyü burada
hatırlatırız, yeniden öğretmeyiz.
Cache, clone, paylaşım
Cache iyidir: aynı dokuyu iki kez indirmezsiniz. Tehlike: paylaşılan Object3D / Material örneğini iki yerde dönüştürüp birbirini ezmek. Holodepth: okuma paylaşılır, yazma çoğaltılır. Sahneye birden fazla instance koyacaksanız clone (veya instancing; derin kaçış sonraki performansta) politikasını yazın.
| Durum | Tercih | Risk |
|---|---|---|
| Aynı doku, iki mesh | Materyal/doku paylaşımı OK | Birinde dispose ötekini kırar |
| Aynı model, iki poz | Scene clone / instancing | Tek kökü iki parent'a bağlamak |
| Geçici preview | Ayrı URL veya bilerek bust | Cache kirlenmesi |
«Clone her şey» bellek yer; «hiç clone yok» mantık yer. Ürün cümlesi tek satır olmalı: kim sahipse o dispose eder.
Dispose: sahiplik mührü
Unmount'ta GPU kaynakları (geometri, materyal, doku, render target)
salınmazsa sekme şişer. R3F birçok intrinsikte yardımcı olur; paylaşılmış
cache ve primitive misafirlerinde sahiplik sizin
sözleşmenizdir. Deklaratif sayfadaki GuestObject örneği eşiği gösterdi;
burada kuralı mühürleriz.
Holodepth üç sahiplik modeli:
- Bileşen özel: yükleyen unmount'ta dispose eder.
- Cache ortak: dispose etme; uygulama kapanışında / bilinçli purge.
- Misafir: çağıran verir, çağıran alır (primitive).
Yanlış model: ortak dokuyu ilk unmount'ta dispose edip ikinci mesh'i siyah bırakmak. Doğru model: ticket'a sahiplik cümlesi yazmak.
Hata yolu: sınır ve sessizlik
404, CORS, bozuk buffer veya desteklenmeyen sıkıştırma «sessiz siyah sahne» üretebilir. React Error Boundary (Vitae'de anlatılan sınır modeli) R3F alt ağacını yakalamak için ürün standardıdır. Holodepth: yükleme sınırında kullanıcıya okunur mesaj + yeniden deneme; konsola yalnız bırakılan reject kabul edilmez.
Güvenlik: kullanıcıdan gelen URL'yi doğrulamadan loader'a vermeyin
(open redirect / beklenmeyen origin). crossOrigin ve CORS
politikası host ile CDN sözleşmesidir; şema teorisi değil, köprü
kırılmasıdır.
Decode'u kareye gömmeyin
useFrame içinde fetch + parse + texture upload yapmak jank üreticisidir. Platform FPS bunu dilim teşhisi olarak işler; burada R3F kuralı net: yükleme askı yolunda, hareket kare yolunda. İlk yerleşimde spike kaçınılmaz olabilir; spike politikasını ürün SLA'sına yazın, sürekli kareye yaymayın.
Progressive: önce düşük çözünürlük proxy, sonra yükseltme. Bu LOD / asset kalitesi sayfasına köprüler; R3F tarafında iki Suspense dalgası veya iki URL kimliği olarak görünür.
Askı pahalı görünebilir; kareye gömülü decode daha pahalıdır.
Güvenli yük: simüle köprü
Örnekler öğretim amaçlıdır; sürüm API'sini doğrulayın. Suspense / Boundary React temeli Vitae'dedir. Model alan spekü yok; TextureLoader ile köprü kalıbı gösterilir. Sabit, bilinen asset yolu kullanın.
Simüle · doku yükü + Suspense sınırı. URL sabit; kullanıcı girdisi yok.
import { Suspense } from 'react'
import { useLoader } from '@react-three/fiber'
import { TextureLoader } from 'three'
// Sabit, bilinen yol · kullanıcı string'i bağlamayın.
const PANEL_MAP = '/assets/demo/panel-albedo.jpg'
function TexturedPanel() {
const map = useLoader(TextureLoader, PANEL_MAP)
// Eğitim notu: colorSpace / flipY ürün sabitine göre mühürlenir (Canvas imzası ile uyumlu).
map.colorSpace = 'srgb'
return (
<mesh>
<planeGeometry args={[2, 1.25]} />
<meshStandardMaterial map={map} roughness={0.55} metalness={0.05} />
</mesh>
)
}
export function TexturedPanelGate() {
return (
<Suspense fallback={null /* veya proxy mesh / DOM spinner */}>
<TexturedPanel />
</Suspense>
)
}
Simüle · sahiplik notlu misafir. Paylaşılan sahne kökünde dispose'u çocuk değil çağıran yapar.
import { useEffect } from 'react'
/** @typedef {'component' | 'cache' | 'caller'} Ownership */
/**
* object: dışarıda üretilmiş THREE.Object3D
* ownership:
* - component → unmount'ta traverse dispose
* - cache → dispose yok (paylaşılan kayıt)
* - caller → dispose çağıranın işi
*/
export function OwnedGuest({ object, ownership = 'caller' }) {
useEffect(() => {
return () => {
if (ownership !== 'component' || !object) return
object.traverse((child) => {
child.geometry?.dispose?.()
const mats = child.material
if (Array.isArray(mats)) mats.forEach((m) => m.dispose?.())
else mats?.dispose?.()
})
}
}, [object, ownership])
if (!object) return null
return <primitive object={object} />
}
Güvenlik özeti: sabit allowlist yolları; origin kontrolü; hata sınırında sızdıran stack'i kullanıcıya ham basmayın; bozuk dosyayı «başarılı yük» sanmayın.
Yükleme tuzakları
- Suspense'siz useLoader: askı yakalanmaz · kırılgan ağaç.
- URL kimliği kayması: her render yeni string · cache delinir.
- Ortak örneği dispose: komşu mesh ölür.
- Tek köke çift parent: clone unutulmuş model.
- Kare içi fetch: jank garantisi.
- Sessiz CORS: fallback yok · «Three bozuk» sanısı.
- Şema ezberi burada: glTF spekü bu sayfaya sızmasın.
Üç yükleme profili
-
01 · Yük
Tek vitrin kahramanı
- Sınır
- Canvas altı tek Suspense
- Fallback
- Proxy / iskelet kabul
- Risk
- Uzun tek spike · SLA'ya yaz
-
02 · Yük
Parça parça reveal
- Sınır
- Parça başına Suspense
- Cache
- Paylaş · clone bilinçli
- Risk
- Layout zıplaması
-
03 · Yük
Paylaşılan kütüphane
- Sahiplik
cache/ caller modeli- Dispose
- İlk unmount'ta kesme
- Risk
- Ömür boyu şişen cache
Fallback UX ve host
Fallback null ise kullanıcı boşluk görür. Holodepth: ya düşük maliyetli proxy mesh (Canvas içi) ya host DOM'da ilerleme. İkisini birden yarıştırmayın. Erişilebilirlik: yük durumu metinsel de duyurulabilsin; yalnız animasyonlu spinner yetmez.
Prefetch (rota öncesi) ürün kararıdır; R3F cache'ini ısıtmak useLoader'ı gizli bir mount ile de yapılabilir. Bunu «sihir» sanmayın: yine aynı kimlik, aynı sahiplik.
Holodepth perspektifleri
Kimliği sabitleyin
Loader + URL ürün anahtarıdır. Rastgele string cache'i ve teşhisi bozar.
Sahiplik cümlesi yazın
Dispose tartışması teknik değil sözleşmeseldir. Ticket'a bir satır.
Askı ve kare ayrı şerit
Yük askıda biter; hareket karede akar. İkisini aynı callback'te ezmeyin.
Teşhis maddeleri
- useLoader Suspense sınırı altında mı?
- URL sabit / allowlist mi?
- Cache paylaşımı clone ile çelişiyor mu?
- Sahiplik modeli (component / cache / caller) yazılı mı?
- Error boundary var mı, sessiz mi?
- Decode useFrame'e mi kaçmış?
- Fallback bilinçli mi?
- glTF şema veya React Suspense 101 bu sayfaya sızmış mı?
Holodepth içgörüsü
«Model gelmedi» çoğu zaman loader bug'ı değil; kimlik, CORS, sahiplik veya sınır eksikliğidir. Önce kargonun pasaportuna bakın, sonra paket speküne inmeyin.
Sonraki kapı: pointer & picking
Kargo yerleştiğinde kullanıcı dokunur / tıklar. Sonraki sayfa Pointer olayları & picking R3F event yüzeyini raycast teorisinden ayırarak anlatır. Imperatif kaçış son yapraktadır.