A founder-voice technical guide to WebGL product page performance: GLB size, texture compression, render-loop scheduling, and the budgets that fit a mobile LCP target.

If you have shipped a WebGL product viewer that loads in 4 seconds on LTE and the conversion lift has not shown up, the issue is rarely the viewer technology. It is the page budget. WebGL viewers fit under a 2-second LCP target on premium DTC if and only if the asset budget, the render loop, and the load timing are all set correctly. This guide covers the three parts of the WebGL performance budget that decide whether the viewer ships fast enough to convert.
A WebGL product page that lands a sub-2-second Largest Contentful Paint on LTE has to fit four constraints. The total payload on the mobile path stays under 3 MB, broken into roughly 200 to 500 KB of viewer code, 1 to 2 MB of compressed model and textures, and the rest for page chrome. The viewer code preloads but the model only fetches when the buyer scrolls near the viewer or taps an affordance. The render loop runs only when something visible is changing, sleeps otherwise to save battery. Textures ship as KTX2 (Basis Universal) and geometry as Draco-compressed GLB. Google's LCP target is 2.5 seconds for a "good" rating at the 75th percentile, and a viewer that meets these four constraints clears that line.
The math is tight on LTE. Every asset gets weighed against the LCP budget. Most production WebGL viewers ship slow because one of the four constraints is loose.
The mobile bundle for a WebGL product page splits roughly:
three/examples/jsm imports rather than loading the whole library.These four together fit under 3 MB if every step uses the right format. They blow past 8 MB if any step skips compression. The 8 MB version is the version most production viewers ship.
Textures dominate the model file size on PBR materials. The compression options:
For a premium DTC product page, KTX2 is the right choice. The build pipeline cost is a few minutes per product. The mobile LCP win is measurable.
The Khronos glTF spec includes two main geometry compression extensions:
For most premium DTC stores, Draco is the simpler and safer choice. Configure the GLTFLoader with a DRACOLoader pointing at the Draco decoder hosted on a CDN. The decoder itself adds about 100 KB but is shared across all products on the site.
WebGL on a static product page is one of the worst battery offenders if the render loop is naive. Most tutorials run the render loop at the browser's animation frame rate (60 fps) regardless of whether anything is happening.
A buyer reading the spec table next to a static viewer does not need the GPU drawing the same model 60 times per second. The fix is an activity-based render loop:
// Pseudocode
let activityCount = 0;
function beginActivity() {
if (activityCount === 0) startRenderLoop();
activityCount++;
}
function endActivity() {
activityCount--;
if (activityCount === 0) stopRenderLoop();
}
Anything that changes the visible scene calls beginActivity when it starts and endActivity when it stops. Auto-rotation. User drag. Animation. Camera transition. The render loop runs only while at least one activity is active.
A static viewer with this loop drops to 0% GPU when the buyer is reading. The battery cost on mobile drops by an order of magnitude.
A WebGL viewer that loads on first paint blocks LCP because the GLB and textures sit in the page's critical path. The fix is to defer the model load until the buyer needs it.
The pattern that works:
This pattern keeps the LCP at the hero photo (fast) while still giving the buyer the viewer when they want it. The 12 MB model that would have killed LCP at the top of the page is now a deferred fetch the buyer triggers consciously.
Some premium DTC pages run a full-screen WebGL canvas as the hero (think a hero scene with the product floating in space). For a top-of-funnel landing page, this can work. For a PDP, it almost never converts.
The reasons:
For a PDP, ship the WebGL viewer as a contained block in the product story flow, not as the full-page hero.
The fastest test is a real phone over a throttled connection.
# In Chrome DevTools, open the page on a real phone via remote debugging.
# Throttle the network to "Slow 3G" or "Fast 3G" and reload.
# Check LCP in the Performance panel.
If the LCP comes in under 2.5 seconds on Slow 3G, the budget is right. If it comes in over 4 seconds, walk the four constraints above and find which one is loose.
Lighthouse and PageSpeed Insights both report LCP. Run the audit weekly on the hero product to catch regressions before the catalog grows.
If your WebGL viewer ships slow, the order of operations is:
These four changes usually move a 6-second LCP to under 2 seconds without touching the viewer code itself.
The Three.js production viewer guide covers the renderer setup that ships with the right defaults. The three ways to embed a 3D model covers when to use Three.js versus model-viewer versus an iframe app.
The buyer is on a phone. LCP at 2.5 seconds is the floor; faster wins. The WebGL viewer fits inside that budget if the four constraints are tight.