Choose a version:
50% The original file has 1132733 bytes (1,106.2k) and is available from the project website.
There you can find the official minified version, too, which brings down the size to 562536 bytes (549.4k, 50%).

After GZIP compression these minified files vary in size:
unpkg
  174204 bytes (170.1k)
CDN
cdnjs
  141588 bytes (138.3k)
CDN
gzip -6 (default)
  140053 bytes (136.8k)
local copy
jsdelivr
  139938 bytes (136.7k)
CDN
gzip -9
  139509 bytes (136.2k)
local copy
libdeflate -12
  134715 bytes (131.6k)
local copy
7zip -mx=9 -tgzip
  134648 bytes (131.5k)
local copy
zultra
  134573 bytes (131.4k)
local copy
kzip -s0 -rn -b0
  134299 bytes (131.2k)
local copy
pigz -11 -n
  134282 bytes (131.1k)
local copy
Zopfli
  134174 bytes (131.0k)
local copy
Zopfli (defluff)
  134172 bytes (131.0k)
local copy

perma-link to the smallest file on my server:
http://minime.stephan-brumme.com/files/threejs/three-r102.min.js (or via HTTPS)

You will automatically get the smallest ThreeJS 102 file, ETag caching is available and
if your browser doesn't support GZIP decompression then the uncompressed version will be sent.

Currently best Zopfli settings

Save 5764 bytes by using my ThreeJS 102 Zopfli version instead of the best available CDN (4.30% smaller than jsdelivr, 134174 vs. 139938 bytes):
You can use my super-compressed files for whatever purpose you like as long as you respect the library's original license agreement.
There are no restrictions from my side - but please avoid hot-linking if you run a high-traffic website.

These command-line settings yielded the best compression ratio so far (Linux version of zopfli-krzymod):
zopfli --i1000000 --mb8 --mls4096 --bsr21 --lazy --ohh

(found March 7, 2019)
Description Value Parameter
iterations 1000000  --i1000000
maximum blocks 8  --mb8
maximum length score 4096  --mls4096
block splitting recursion 21  --bsr21
lazy matching in LZ77 yes  --lazy
optimized Huffman headers yes  --ohh
initial random W for iterations 1  --rw1
initial random Z for iterations 2  --rz2

Even Smaller Files Thanks To Defluff

Zopfli's output can be further optimized by the defluff tool.
In this particular case, defluff saves 2 more bytes (134172 bytes).

Verify file integrity

After decompression, my uncompressed files are identical to the original ones:

MD5:
curl --silent --compressed https://raw.githubusercontent.com/mrdoob/three.js/r102/build/three.min.js --location | md5sum
8a2f147866977f52d1a094110c385e82  -
curl --silent --compressed https://minime.stephan-brumme.com/files/threejs/three-r102.min.zopfli.js.gz | md5sum
8a2f147866977f52d1a094110c385e82  -

SHA1:
curl --silent --compressed https://raw.githubusercontent.com/mrdoob/three.js/r102/build/three.min.js --location | sha1sum
5af0636a54a5fe0c1f697be3184f9640e7ae1242  -
curl --silent --compressed https://minime.stephan-brumme.com/files/threejs/three-r102.min.zopfli.js.gz | sha1sum
5af0636a54a5fe0c1f697be3184f9640e7ae1242  -

CDN Size (compressed) MD5 (uncompressed) Comment / Diff Timestamp
unpkg 174204 bytes 0bc6683f4e7e261b983ca84c8aedf5ef < (function(l,ka){"object"===typeof exports&&"undefined"!==t [...]
> (function(l,ka){"object"===typeof exports&&"undefined"!==t [...]
< Array.isArray(e)?b[c][d]=e.slice():b[c][d]=e}}return b}fun [...]
> Array.isArray(e)?b[c][d]=e.slice():b[c][d]=e}}return b}fun [...]
< 0,h):0===k.count?console.error("THREE.WebGLObjects.updateB [...]
> 0,h):0===k.count?console.error("THREE.WebGLObjects.updateB [...]
< Object.defineProperties(this,{position:{configurable:!0,en [...]
> Object.defineProperties(this,{position:{configurable:!0,en [...]
< new F(v,3));this.addAttribute("uv",new F(t,2))}function M( [...]
< null;this.clipShadows=this.clipIntersection=!1;this.shadow [...]
[...]
(invalid)
cdnjs 141588 bytes 0bc6683f4e7e261b983ca84c8aedf5ef < (function(l,ka){"object"===typeof exports&&"undefined"!==t [...]
> (function(l,ka){"object"===typeof exports&&"undefined"!==t [...]
< Array.isArray(e)?b[c][d]=e.slice():b[c][d]=e}}return b}fun [...]
> Array.isArray(e)?b[c][d]=e.slice():b[c][d]=e}}return b}fun [...]
< 0,h):0===k.count?console.error("THREE.WebGLObjects.updateB [...]
> 0,h):0===k.count?console.error("THREE.WebGLObjects.updateB [...]
< Object.defineProperties(this,{position:{configurable:!0,en [...]
> Object.defineProperties(this,{position:{configurable:!0,en [...]
< new F(v,3));this.addAttribute("uv",new F(t,2))}function M( [...]
< null;this.clipShadows=this.clipIntersection=!1;this.shadow [...]
[...]
(invalid)
jsdelivr 139938 bytes 0bc6683f4e7e261b983ca84c8aedf5ef < (function(l,ka){"object"===typeof exports&&"undefined"!==t [...]
> (function(l,ka){"object"===typeof exports&&"undefined"!==t [...]
< Array.isArray(e)?b[c][d]=e.slice():b[c][d]=e}}return b}fun [...]
> Array.isArray(e)?b[c][d]=e.slice():b[c][d]=e}}return b}fun [...]
< 0,h):0===k.count?console.error("THREE.WebGLObjects.updateB [...]
> 0,h):0===k.count?console.error("THREE.WebGLObjects.updateB [...]
< Object.defineProperties(this,{position:{configurable:!0,en [...]
> Object.defineProperties(this,{position:{configurable:!0,en [...]
< new F(v,3));this.addAttribute("uv",new F(t,2))}function M( [...]
< null;this.clipShadows=this.clipIntersection=!1;this.shadow [...]
[...]
March 5, 2019 @ 14:14

Note: only the MD5 hashes are shown to keep things simple.

Other Versions

Available ThreeJS versions at minime.stephan-brumme.com:

148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50

The project site contains an overview how well these versions were compressed.
Other interesting projects are AngularJS, BackboneJS, Bootstrap, D3, Dojo, Ember, jQuery, Knockout, lodash, React, Socket.IO, UnderscoreJS and Vue.

Changelog

Best Zopfli parameters so far:
Size Improvement Parameters Found
134174 bytes -1 byte zopfli --i1000000 --mls4096 --bsr21 --lazy --ohh March 7, 2019 @ 09:06
134175 bytes -7 bytes zopfli --i100000 --mls4096 --bsr21 --lazy --ohh March 5, 2019 @ 23:16
134182 bytes -11 bytes zopfli --i10000 --mls4096 --bsr21 --lazy --ohh March 5, 2019 @ 19:28
134193 bytes -11 bytes zopfli --i1000 --mls4096 --bsr21 --lazy --ohh March 5, 2019 @ 16:05
134204 bytes -20 bytes zopfli --i1000 --mls4096 --bsr19 --lazy --ohh March 5, 2019 @ 15:26
134224 bytes zopfli --i100 --mls4096 --bsr21 --lazy --ohh March 5, 2019 @ 14:22

If there are multiple parameter sets yielding the same compressed size, only the first one found is shown.

Most recent activity on July 20, 2020 @ 12:51.

Heatmaps

This Zopfli heatmap visualizes how compression changes when modifying the --bsr and --mls parameter.
Cell's contents is the best filesize achieved (in bytes, hover with mouse over cells to see number of iterations).

Good parameters are green, bad are red. The best and worst are bold as well.
The brightness of the blue background color indicates how many iterations were processed:
10,000, 100,000 or 1,000,000.
bsr \ mls
2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768
bsr \ mls
2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768
134436 134437 134515 134431 134437 134426 134495 134494 134388 134465 134437 134489 134487 134431 134446
134494 134453 134479 134502 134502 134316 134504 134496 134350 134501 134352 134482 134473 134489 134476
134548 134475 134482 134479 134489 134440 134487 134457 134332 134546 134465 134236 134546 134353 134280
134458 134471 134451 134479 134485 134437 134467 134508 134487 134444 134487 134428 134451 134280 134415
134268 134482 134462 134454 134476 134452 134456 134444 134475 134462 134273 134451 134445 134451 134391
134467 134482 134437 134480 134472 134475 134490 134344 134343 134464 134350 134432 134264 134450 134408
134489 134450 134443 134442 134428 134439 134455 134513 134457 134454 134454 134179 134287 134441 134419
134431 134474 134439 134450 134461 134477 134446 134524 134478 134448 134497 134454 134268 134446 134414
134464 134458 134436 134456 134475 134464 134479 134501 134308 134453 134341 134420 134470 134459 134432
134452 134452 134443 134440 134430 134391 134419 134512 134442 134459 134327 134198 134473 134462 134438
134448 134457 134444 134486 134531 134470 134489 134526 134290 134263 134353 134264 134476 134472 134409
134452 134463 134439 134462 134495 134458 134488 134509 134296 134477 134278 134406 134291 134485 134409
134332 134516 134474 134454 134459 134476 134481 134502 134348 134454 134349 134236 134475 134450 134383
134465 134473 134446 134446 134526 134473 134499 134512 134348 134435 134287 134404 134448 134457 134279
134471 134466 134476 134463 134462 134465 134503 134499 134477 134432 134347 134450 134446 134446 134391
134467 134466 134481 134462 134481 134465 134488 134500 134479 134432 134345 134191 134447 134441 134409
134476 134468 134473 134477 134470 134452 134494 134514 134340 134432 134434 134440 134445 134446 134278
134464 134465 134464 134447 134436 134463 134448 134497 134452 134440 134353 134174 134449 134448 134407
134450 134468 134438 134466 134480 134460 134434 134513 134475 134451 134441 134454 134450 134456 134382
134418 134465 134457 134454 134444 134465 134473 134511 134476 134436 134345 134451 134443 134455 134278
134457 134457 134460 134467 134441 134507 134486 134497 134306 134453 134336 134211 134267 134457 134413
134448 134452 134441 134458 134459 134466 134435 134512 134475 134409 134213 134455 134284 134467 134430
134472 134468 134454 134464 134464 134451 134485 134494 134341 134437 134350 134233 134263 134452 134408

Due to the Monte Carlo design of my search algorithm, not all parameters have reached the same number of iterations yet:
Iterations Min. Bytes Reduction Coverage
100 134224 bytes 100%
1,000 134193 bytes -31 bytes 100%
10,000 134182 bytes -11 bytes 100%
100,000 134175 bytes -7 bytes 0.58%
1,000,000 134174 bytes -1 byte 0.29%
10,000,000

KZIP has far less options available for tuning/optimization. I only played around with the number of blocks (parameter -n):
Blocks Min. Bytes Compared To Best Zopfli Compared To Best KZIP
134299 bytes +125 bytes (+0.09%)
134958 bytes +784 bytes (+0.58%) +659 bytes
134917 bytes +743 bytes (+0.55%) +618 bytes
134763 bytes +589 bytes (+0.44%) +464 bytes
134655 bytes +481 bytes (+0.36%) +356 bytes
134456 bytes +282 bytes (+0.21%) +157 bytes
134406 bytes +232 bytes (+0.17%) +107 bytes
134422 bytes +248 bytes (+0.18%) +123 bytes
134388 bytes +214 bytes (+0.16%) +89 bytes

Non-DEFLATE Algorithms

Archivers based on completely different compression algorithms often produce superior results.
Unfortunately, browsers only support gzip compression at the moment.
However, support for Brotli is constantly growing - but your browser doesn't support it.
Algorithm Program Parameters Size Compared To Best Zopfli
ZPAQ (Wikipedia) zpaq zpaq -method 69 90293 bytes -43881 bytes (-32.70%)
RAR (proprietary) RAR rar a -m5 -md64m -mc63:128t -mt1 103923 bytes -30251 bytes (-22.55%)
PPMd (Wikipedia) 7zip 7za a -mx=9 -m0=ppmd 107660 bytes -26514 bytes (-19.76%)
Brotli (Wikipedia) brotli brotli -q 11 114261 bytes -19913 bytes (-14.84%)
LZMA2 (Wikipedia) xz xz -9 114936 bytes -19238 bytes (-14.34%)
Burrows-Wheeler transform (Wikipedia) bzip2 bzip2 -9 119601 bytes -14573 bytes (-10.86%)
Zstandard (Wikipedia) zstd zstd -19 120934 bytes -13240 bytes (-9.87%)

Detailled Analysis

I wrote a DEFLATE decoder in Javascript. Click the button below to start a client-side analysis of the smallest gzipped files (may take a second):


Notes: pigz is a fast open source multi-threaded implementation of gzip written by one of the original authors of gzip.
However, when using compression level 11, pigz actually switches to the slower Zopfli algorithm and isn't multi-threaded anymore.
KrzyMOD's extensions to Zopfli offer the highest level of configuration and is therefore used for my brute-force search.
Ken Silverman wrote the closed-source KZIP compression program and Jonathon Fowler ported it to Linux.
Defluff was created by Joachim Henke; DeflOpt is a tool by Ben Jos Walbeehm.

website made by Stephan Brumme in 2015 and still improving in 2024.
all timestamps are displayed in central european time. see my changelog.
no flash, not even images or external css files - and everything squeezed into a single html file.
which was handsomely compressed before releasing it into the wild internet - obviously.

please visit my homepage and my blog, too.
email: minime (at) stephan-brumme.com

All trademarks are property of their respective owners. You know, the boring legal stuff.