Three.js 30,815 has no semantic versioning. Each release is a revision, rNNN, published to npm 2,036 as 0.NNN.x: r186 is three@0.186.0 (8 September 2026) plus the 0.186.1 fix (24 September). Releases come every one to three months, and any may remove an API. The wiki's Migration Guide lists the breaking changes; deprecation warnings last ten releases, so upgrade old projects ten revisions at a time. npm's ^0.186.1 accepts 0.186.2 but never 0.187.0. npm view three version prints 0.186.1, and THREE.REVISION is '186' at run time. Date a sample before copying it: THREE.Geometry went in r125, outputEncoding became outputColorSpace in r152, and WebGL 1 support ended in r163.
<!doctype html>
<style>
body { margin: 0; background: #f5f1e8; font: 13px system-ui, sans-serif; }
canvas { display: block; width: 100%; max-width: 600px; height: auto; }
</style>
<script type="importmap">
{ "imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.186.1/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.186.1/examples/jsm/" } }
</script>
<script type="module">
import * as THREE from 'three';
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
renderer.setSize(600, 360);
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
scene.background = new THREE.Color('#f5f1e8');
const camera = new THREE.PerspectiveCamera(40, 600 / 360, 0.1, 50);
camera.position.set(0, 0.4, 5);
scene.add(new THREE.HemisphereLight('#ffffff', '#8d6e63', 1.5));
const sun = new THREE.DirectionalLight('#ffffff', 2);
sun.position.set(2, 3, 4);
scene.add(sun);
// Draw a label on a canvas; used as textures below
function label(lines, bg, fg, w = 512, h = 256) {
const canvas = Object.assign(document.createElement('canvas'), { width: w, height: h });
const g = canvas.getContext('2d');
g.fillStyle = bg; g.fillRect(0, 0, w, h);
g.fillStyle = fg; g.textAlign = 'center';
lines.forEach(([text, size], i) => {
g.font = `bold ${size}px Georgia`;
g.fillText(text, w / 2, h * (i + 1) / (lines.length + 1) + size / 3);
});
const texture = new THREE.CanvasTexture(canvas);
texture.colorSpace = THREE.SRGBColorSpace;
return texture;
}
// THREE.REVISION is the release number as a string: '186' for three@0.186.x
const cover = label([['three.js', 44], ['r' + THREE.REVISION, 110]], '#1f5f8b', '#fff3e0', 256, 360);
const side = new THREE.MeshStandardMaterial({ color: '#f3ecdc' });
const book = new THREE.Mesh(new THREE.BoxGeometry(1.2, 1.7, 0.25),
[side, side, side, side, new THREE.MeshStandardMaterial({ map: cover }),
new THREE.MeshStandardMaterial({ color: '#1f5f8b' })]);
book.position.set(-1.3, 0.4, 0);
scene.add(book);
// A timeline of releases that removed or renamed an API
const events = [[125, 'THREE.Geometry removed'], [152, 'outputColorSpace'], [163, 'WebGL 1 dropped'],
[183, 'Timer replaces Clock'], [+THREE.REVISION, 'this page']];
events.forEach(([rev, text], i) => {
const tag = new THREE.Mesh(new THREE.PlaneGeometry(1.9, 0.34),
new THREE.MeshBasicMaterial({ map: label([[`r${rev} ${text}`, 60]], i === 4 ? '#e09a10' : '#ffffff', '#263238', 1024, 180) }));
tag.position.set(1.2, 1.3 - i * 0.42, 0);
scene.add(tag);
});
renderer.setAnimationLoop((time) => {
book.rotation.y = Math.sin(time / 1000) * 0.6;
renderer.render(scene, camera);
});
console.log('THREE.REVISION =', THREE.REVISION);
</script>