Every three.js site that gets posted to the forum's Showcase category is someone's proud moment. We wanted one honest number for the whole crowd: how many bytes, requests and seconds does a typical showcase site cost a phone on first load? So we ran Lighthouse against 192 of them, on one day, with the same settings, and kept every result. The short version: the median site is lighter than most people would guess at 1.2 MB, but a quarter ship more than 5 MB before you touch anything, and 64% miss Google's "poor" line for Largest Contentful Paint. The full dataset is at the end of this post.
What we measured
We measured the first page load of 192 publicly posted three.js showcase sites with Lighthouse 12.8 in its default mobile setup. The sample came from the three.js forum's Showcase category: the 269 most recently active topics, first post only, one URL per domain, with code hosts, sandboxes, social links and files removed. That left 230 sites. We took 5 out by hand because the forum post credited them rather than showed them, and 33 could not be measured in our lab at all (21 produced no report, 3 hung, 4 never painted, the rest timed out or errored). We report that as a number instead of hiding it, because the sites that break a headless browser are probably not the light ones.
Every site got one run, on 2026-10-23, from an ARM server with software WebGL. That matters for how you read the results. Bytes, request counts and the network-bound timings (First and Largest Contentful Paint) are representative. Anything that depends on the main thread, which includes Total Blocking Time and therefore the performance score, is overstated for WebGL pages, because our lab rasterises the GPU work on a CPU. Where we quote the score we mark it with an asterisk. The method, with every filter and threshold, is written up in METHOD.md.
How heavy a first load is
The median showcase site transfers 1.2 MB on first load, and 44% come in under 1 MB. The average is 5.7 MB, which tells you the tail is long: 24% of sites ship more than 5 MB, 14% more than 10 MB, and the biggest first load we recorded was 147.3 MB. For 88 of the 192 sites Lighthouse stopped waiting before the page went quiet, so their bytes are a floor, not a total.
| Metric | Median | 75th percentile | 90th percentile |
|---|---|---|---|
| First-load transfer | 1.2 MB | 4.6 MB | 13.9 MB |
| Requests | 28 | 60 | 120 |
| JavaScript | 391 KB | 718 KB | 1.2 MB |
| Images and textures | 78 KB | 591 KB | 3.7 MB |
| First Contentful Paint | 2.8 s | 4.7 s | 7.9 s |
| Largest Contentful Paint | 6.0 s | 13.5 s | 30.1 s |
| Performance score* | 46 | 65 | 85 |
* Performance score and anything built on Total Blocking Time are biased down in this lab (software WebGL). Read them as a ranking, not as what a phone with a GPU would score.
What the bytes are
For the median site the biggest slice is JavaScript: 391 KB of it, which is 35% of that site's bytes, with three.js itself usually bundled inside. But across all 192 sites added together, JavaScript is only 10% of the traffic. The aggregate is dominated by the heavy minority: 3D asset files (glTF, binary buffers, HDR environments, compressed textures) are 39% of every byte we recorded, even though only 27% of sites load a file we could recognise as a 3D asset by its URL. Images and textures are another 28% in aggregate, and video 10%. Fonts barely register at a median of 55 KB.
In other words, a three.js site is not heavy because of three.js. The library plus a bundler costs a few hundred kilobytes. Sites get heavy when they fetch a scanned model, an 8K environment map or a texture set that was exported for a desktop renderer, and fetch it all before the first frame. 14% of sites ship more than 1 MB of JavaScript; 12% make more than 100 requests; 9% load WebAssembly, usually a physics engine or a Draco decoder.
How fast it feels
The median Largest Contentful Paint is 6.0 s, and only 22% of sites hit Google's "good" threshold of 2.5 seconds. 64% are past the 4-second "poor" line. First Contentful Paint is kinder, with a median of 2.8 s, which usually means a loading screen or a hero text block arrives, then the scene takes its time. Layout shift is a non-issue for canvas apps: the median CLS is effectively zero and only 3% of sites are above 0.25.
The performance score tells the same story with the lab caveat attached: median 46*, 52% under 50, and 8% at 90 or above. The 67 sites where three.js was visible as an unbundled file (a CDN build or a modules folder) were heavier than the rest, with a median first load of 1.9 MB and a median LCP of 6.8 s. Those are often demos and experiments that load textures straight from the source, which is exactly the thing a production build should not do.
The ten lightest sites
Ten sites deliver a real three.js experience in under 197 KB, and six of them also post a Largest Contentful Paint under 2.5 seconds. They have something in common: the geometry is procedural or tiny, the textures are generated or small, and nothing big is fetched before the first frame. Click through to the makers' forum posts to see how they did it.
| Site (↗ = forum post) | First load | Requests | LCP | Score* |
|---|---|---|---|---|
| gamaccho.github.io ↗ | 30 KB | 3 | 7.9 s | 26 |
| incredible-space.com ↗ | 33 KB | 8 | 1.3 s | 99 |
| tiki-dash.com ↗ | 48 KB | 5 | 1.7 s | 99 |
| pixelwareportfolio.blogspot.com ↗ | 69 KB | 9 | 2.8 s | 94 |
| wazo3d.com ↗ | 102 KB | 8 | 1.0 s | 85 |
| aksites.pl ↗ | 102 KB | 16 | 2.6 s | 92 |
| masterblaster.se ↗ | 130 KB | 16 | 2.5 s | 95 |
| exo-view.com ↗ | 134 KB | 17 | 1.9 s | 100 |
| terrainlab.netlify.app ↗ | 150 KB | 6 | 1.3 s | 72 |
| company-named.com ↗ | 197 KB | 6 | 3.2 s | 86 |
The ten biggest worlds
The heaviest ten are games, flight trackers and whole cities, and they are big on purpose. The interesting detail is that size and speed are not the same axis. The 147.3 MB site at the top paints its largest element in under a second, because it streams the world after showing the menu, while sites a quarter its size keep the visitor on a blank canvas for a minute. Streaming after first paint is the difference.
| Site (↗ = forum post) | First load | Requests | LCP | Score* |
|---|---|---|---|---|
| hardroad.xyz ↗ | 147.3 MB | 155 | 0.9 s | 61 |
| brisbane.exposed ↗ | 65.9 MB | 39 | 124.1 s | 27 |
| nova-defender.expo.app ↗ | 55.2 MB | 70 | 6.7 s | 37 |
| monsteriademo.netlify.app ↗ | 49.1 MB | 7 | 1.5 s | 65 |
| flightobserver3d.org ↗ | 41.5 MB | 115 | 2.6 s | 53 |
| chatgpt.site ↗ | 35.1 MB | 44 | 1.2 s | 65 |
| ryoccom.com ↗ | 33.9 MB | 32 | 1.6 s | 59 |
| prodiam.co.za ↗ | 32.5 MB | 21 | 68.2 s | 41 |
| graveyard-pinball.vercel.app ↗ | 25.5 MB | 189 | 86.4 s | 25 |
| discball3d.com ↗ | 24.5 MB | 87 | 25.0 s | 25 |
Our own pages, measured the same way
Our homepage transferred 4.5 MB on first load, heavier than 74% of the showcase sites, with a Largest Contentful Paint of 6.3 s, right at the sample median, and a lab score of 38*. The single largest request is the sun model at 1.9 MB. Client City, our walkable 3D portfolio, transferred 3.6 MB, with 39 texture requests before the first frame and a Largest Contentful Paint of 16.7 s, slower than 79% of the sample, when we first measured it. Rebuilt with a streaming loader the week before this post went out, it now transfers 2.4 MB and paints its largest element at 7.2 s, still slower than 57% of the sample. We are publishing a study about everyone else's weight, so those numbers go in too. Our two pages are not in the dataset; they were measured with the identical setup for comparison only.
What we are changing because of this
The lightest sites in the sample taught us more than the heaviest. Three rules came out of it. First, a first-load budget: 1 to 3 MB before the first frame, the range the lighter half of the showcase lives in, and everything else streams after the scene is on screen. Second, textures and models are loaded after the first paint, not before, and in a compressed GPU format (KTX2 with Basis, Draco or meshopt for geometry), which is the second half of the change Client City needs: its textures now stream in after the first paint, but not yet in a GPU format. Third, procedural beats baked wherever a visitor cannot tell the difference: generated terrain and materials cost kilobytes, scanned ones cost megabytes. We already cut our service pages from 2.7 MB to 0.4 MB this month by stopping a 1.9 MB model from being prefetched on pages that never show it, Client City's first frame went from 10.6 MB to 2.4 MB with the streaming loader, and the homepage is next.
Get the data
Everything is downloadable: sites.csv (192 rows, one per site, with the forum post each one came from), summary.json (every number in this post), METHOD.md, the hand exclusions and the list of sites we could not measure. The scripts and the raw Lighthouse reports are on GitHub: threejs-showcase-weight-study. Bytes are Lighthouse transfer sizes, MB means 1,000,000 bytes, percentiles are linear interpolation. The crawl read the forum's public JSON at one request per second with a User-Agent that names us, and each site got at most three header requests and one page load. If your site is in the list and you would rather it was not, tell us and we will remove it from the published files.
If you want your own three.js site measured against this sample, or you are weighing a 3D homepage and want to know what it will cost your visitors, that is the kind of thing we do every week at our 3D web design studio.
