React Three Fiber does not change the economics of a GLB: useGLTF ultimately hands the asset to Three.js. A large texture payload still has to cross the network, and every optional codec still needs a compatible decoder. The reliable workflow is to create one reviewed delivery asset, then generate React structure without silently optimizing the same model a second time.
Scope: This guide stays at the asset layer. OptimizeGLB can reduce bytes, texture dimensions, duplicate data, and triangle count, or remove an extension requirement. It cannot repair Suspense boundaries, progress reporting, cache disposal, or WebGL context bugs.
Asset decision path
Optimize the file for the runtime you actually ship
- 01
Source pressure
Large downloads, oversized textures, repeated scene data
- 02
OptimizeGLB decision
Choose the texture, geometry, and compatibility contract once
- 03
React Three Fiber handoff
One reviewed GLB for useGLTF and gltfjsx
Encoded size, decode cost, and runtime complexity are separate measurements. A codec is useful only when the complete handoff improves.
What teams actually run into
These are primary reports from framework users, filtered to symptoms that can be changed at the asset layer. Each response is intentionally narrower than the original runtime problem.
01
The first visit spends most of its time fetching model data
In an R3F support discussion, a developer traced a 160 MB page payload largely to textures. Maintainers pointed back to texture reduction and GLB compression rather than a React-specific optimization.
OptimizeGLB response: Cap texture dimensions to the pixels the model can display, prune unused data, deduplicate repeated resources, and test Draco for geometry. If the scene is still triangle-bound, create a separately reviewed simplified variant.
R3F discussion #784 โ a 160 MB web payload and the recommendation to reduce texture and model bytes02
KTX2 saves bytes but complicates the useGLTF path
A current Drei issue describes multiple KTX2 loaders, repeated WASM decoders, and awkward preloading when several generated components each configure their own transcoder.
OptimizeGLB response: Do not emit KTX2 merely because it is the most advanced option. Use WebP or core JPEG/PNG when you want the simplest useGLTF path. Choose KTX2 only when the application already owns a tested, shared KTX2Loader setup.
Drei issue #2639 โ an open report about KTX2 setup across useGLTF and gltfjsx components03
A large GLB appears to leave the loading UI frozen
One Drei report describes a 30 MB GLB whose progress display remains at zero until the single asset finishes. Fewer transferred bytes shorten that wait even though they do not change the loader's item-based progress semantics.
OptimizeGLB response: Reduce the delivery GLB and its textures before spending time tuning the progress UI. Measure a cold network load, not a cached reload, and keep the loading-state fix as a separate application task.
Boundary: OptimizeGLB can shorten the transfer; it cannot make Drei report byte-level progress for a single request.
Drei issue #2003 โ a report about a 30 MB GLB appearing stuck until download completesChoose the output by compatibility, not fashion
Start with a control that uses the fewest optional extensions. Add a codec only when its measured benefit is worth the decoder and version requirement it creates.
Scroll horizontally to compare โ
| Decision | OptimizeGLB output | Why |
|---|---|---|
| Compatibility baseline | Original textures, pruning and deduplication; Draco and simplification off | Separates an asset defect from a decoder or lossy-transform regression. |
| General web delivery | WebP textures at a reviewed size, Draco on, simplification off | Reduces transfer while staying on useGLTF's common browser path. |
| GPU texture delivery | KTX2 only with a shared, tested KTX2Loader configured through extendLoader | KTX2 is an application contract, not an asset-only switch. |
| Dense background asset | Create a separate simplified variant and compare silhouettes and animation | Draco shrinks encoded geometry; simplification is what lowers triangle count. |
A release workflow for React Three Fiber
Change one expensive dimension at a time. That makes a failed import or visual regression attributable to a decision instead of an opaque preset.
- 01
Measure the source on a cold load
Record GLB bytes, texture contribution, triangle count, draw calls, and the time until the model is visible.
- 02
Create the compatible control
Run OptimizeGLB with cleanup only. Confirm that useGLTF and the generated component still expose the expected nodes, materials, and animations.
- 03
Change one expensive dimension
Resize or convert textures first when images dominate; enable Draco when geometry dominates. Keep a result for each test.
- 04
Generate JSX from the reviewed output
Run gltfjsx without its transform flag unless you intentionally want another prune, resize, format conversion, and compression pass.
- 05
Ship the decoder contract with the asset
If the GLB requires Draco or KTX2, verify the exact production decoder path and a cold load before replacing the baseline.
The useful boundary
For R3F, the best asset is not the one with the most codecs. It is the smallest reviewed GLB whose required decoders are already part of the application. OptimizeGLB should make that tradeoff explicit before gltfjsx turns the scene into React code.
Documentation and primary reports
Official documentation establishes support. Issue trackers and framework forums show the failure modes teams encounter in real projects. These links are the basis for the recommendations above.
Official documentation
- Drei useGLTF documentationDraco defaults, KTX2 extendLoader setup, and preloading
- gltfjsxthe transform pipeline, texture resize behavior, pruning, compression, and instancing
- React Three Fiber useLoaderthe underlying loader, cache, preload, and clear APIs
- Three.js GLTFLoadersupported glTF extensions and decoder configuration
Field reports
- R3F discussion #784large texture payload and slow first load
- Drei issue #2639KTX2 loader setup across multiple GLBs
- Drei issue #2003large single-file progress appearing frozen