Library / SDK
mrdoob/three.js avatar
mrdoob/three.js

three.js: a JavaScript 3D library for the browser, and what it costs to adopt

three.js is an easy-to-use, lightweight, cross-browser JavaScript 3D library with WebGL and WebGPU renderers, plus SVG and CSS3D renderers available as addons.

115,553 stars36,556 forksJavaScriptMIT

At a glance

What is it?
three.js is an MIT-licensed JavaScript 3D library that renders through WebGL and WebGPU. It is a rendering toolkit, not a framework, and the release cadence is what decides your upgrade budget.
Who is it for?
Adopt three.js if you need browser 3D rendering and can accept a library that ships a new release roughly every two months, with migration notes kept in the wiki rather than in the package. Do not adopt it if you want a scene graph with batteries included, a physics engine, or a component model that manages your application state; three.js gives you a renderer and leaves the rest to you.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What three.js actually solves, and who ends up using it

Browsers give you a low-level drawing API and nothing else. WebGL exposes shaders, buffers and draw calls; it has no concept of a camera, a mesh, or a scene graph. three.js fills that gap. The README describes the aim plainly: "an easy-to-use, lightweight, cross-browser, general-purpose 3D library." The repository is JavaScript, the licence is MIT, and the default branch is dev.

The audience is narrower than the download numbers suggest. If you are building a product configurator, a data visualisation with depth, a browser game, or an interactive explainer, three.js is the layer between your data and the GPU. If you are building a CRUD application, you will not need it. The library assumes you are comfortable with vectors, matrices and a render loop, or willing to learn them.

One thing to settle early: three.js is not a framework. It has no opinion about routing, state, or component structure. The README links to examples, docs, a manual, a wiki and a forum, which is where the application-level guidance lives. Everything above the renderer is your problem.

The mechanism: scene graph in, draw calls out

The core loop is short. You build a scene graph of Object3D nodes, attach a camera, and hand both to a renderer, which walks the graph each frame and issues draw calls. Geometry and material are separate objects, so the same BoxGeometry can be reused across many meshes with different materials, and the renderer decides what to upload to the GPU.

What ships in the package matters here. The package.json exports a main build at ./build/three.module.js for import and ./build/three.cjs for require, plus ./webgpu for the WebGPU build and ./tsl for the node-based shading language. Addons are not bundled into the core build; they are exposed through ./addons, which maps to examples/jsm. The README notes that the current builds only include WebGL and WebGPU renderers, while SVG and CSS3D renderers are available as addons. So a CSS3D label is an import from the addons path, not part of the core.

The repository layout confirms the split: src/ for the library, examples/jsm/ for addons and controls, examples/ for the runnable demos, manual/ and docs/ for prose, and test/ for unit tests. The package.json sideEffects field lists ./src/nodes/**/*, which is a signal to bundlers that the node system is not safely tree-shakeable. If bundle size is a constraint, that is the field to look at first.

Install three.js and render a first cube

Install from npm. The package name is three, and the version in the repository package.json is 0.186.0, which does not match the release tag r185; the tags and the npm version move on separate numbering, so do not assume r185 means 185 on npm.

bash
npm install three

The README's usage example builds a scene, a camera, a box and a WebGL renderer, then starts an animation loop. This is the smallest program that produces something on screen.

javascript
import * as THREE from 'three';

const width = window.innerWidth, height = window.innerHeight;

const camera = new THREE.PerspectiveCamera( 70, width / height, 0.01, 10 );
camera.position.z = 1;

const scene = new THREE.Scene();

const geometry = new THREE.BoxGeometry( 0.2, 0.2, 0.2 );
const material = new THREE.MeshNormalMaterial();

const mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );

const renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( width, height );
renderer.setAnimationLoop( animate );
document.body.appendChild( renderer.domElement );

The README states that if everything goes well you should see a result matching the linked jsfiddle. Note that the snippet calls animate in setAnimationLoop but the README excerpt does not define that function; you supply it, and it is where you update the mesh rotation and call renderer.render( scene, camera ).

To work against the repository itself rather than the npm package, the README gives a shallow clone because the full history is roughly 2 GB.

bash
git clone --depth=1 https://github.com/mrdoob/three.js.git

The dev script runs a build step and then a local server on port 8080.

bash
npm run dev

That serves the examples directory, which is the fastest way to see how a feature is meant to be wired before you write your own version of it.

The release cadence is the real adoption cost

Releases arrive on a tight schedule: r183 on 2026-02-20, r184 on 2026-04-16, r185 on 2026-07-01. That is roughly every two months, and the last push to the repository was on 2026-07-01. The project is not archived, and the pace has not slowed.

This is the trade-off most teams underestimate. A two-month cadence means API changes land regularly, and the README points to a Migration Guide in the wiki rather than shipping migration notes inside the package. Your dependency on three.js is therefore a recurring maintenance line, not a one-time install. Addons are the sharp edge: they live under examples/jsm and are exposed through ./addons, and the README itself frames SVG and CSS3D renderers as addons rather than core. Addon paths and signatures are where upgrades tend to bite.

If you pin a version and defer upgrades, nothing breaks immediately. But the gap compounds, and a jump across several releases is harder to reason about than a steady one. The honest framing is that three.js charges rent in upgrade time instead of licence fees.

Where three.js is the wrong tool

The README is explicit that the current builds only include WebGL and WebGPU renderers. If your target environment cannot rely on either, three.js is not the answer, and that includes contexts where GPU access is unavailable or blocked. The SVG and CSS3D renderers exist as addons, but they are not the default path and they are not a substitute for WebGL in a scene with heavy geometry.

The second boundary is scope. three.js renders. It does not simulate physics, it does not manage application state, and it does not give you a component lifecycle. Teams that expect a framework-shaped tool end up writing one, badly, on top of the renderer. If your project is mostly UI with a small 3D element, the cost of the render loop plus the upgrade cadence may exceed the value, and a simpler canvas or CSS approach will be easier to keep alive.

The third is the node system. The sideEffects entry for ./src/nodes/**/* means bundlers cannot freely drop unused node code. If you are not using TSL or the WebGPU node pipeline, that is dead weight you should measure before shipping.

How three.js differs from a full game engine

The closest alternative in practice is a browser game engine such as Babylon.js, which takes the opposite approach: it ships a broader integrated stack, including its own tooling and higher-level systems, in one package. The difference is where the seams are. three.js keeps the core small and pushes renderers, controls and loaders into examples/jsm, so you assemble the stack yourself and you know exactly what is in it. An integrated engine hands you more out of the box and asks you to accept its opinions about scene management, assets and application structure.

Neither choice is strictly better. If you want to prototype a game with physics and asset pipelines in a week, the integrated engine saves you writing glue. If you want a rendering layer you can embed in an existing application and control precisely, three.js's smaller surface is the advantage. The cost of that control is that every subsystem you need is a decision you make and a dependency you track through the next release.

For non-game work, the comparison is less about engines and more about whether you need 3D at all. A charting library will beat three.js for a flat line chart every time.

Licence, maintenance and what to verify before you commit

The licence is MIT, which is permissive and imposes no copyleft obligation on your application. That is a genuine advantage for commercial products, and it is the reason three.js appears inside so many closed-source builds. This is a description of the licence identifier, not legal advice; read the LICENSE file in the repository and get your own counsel if the terms matter to your organisation.

Maintenance is visible in the release history rather than in a support contract. Releases land on a two-month rhythm and the last push was on 2026-07-01. The repository carries SECURITY.md and a test suite with separate lint and unit-test scripts, which tells you the project expects contributors to run checks before submitting changes. There is no commercial support tier described in the README or package.json.

Upgrade cost is the line item to budget. The README links a Migration Guide, and the wiki is where breaking changes are explained. Before adopting, check that the addons you plan to use are present in examples/jsm, confirm which renderer your target browsers can run, and decide whether you will track releases continuously or pin and schedule the jump.

Editorial conclusion

Adopt three.js if you need browser 3D rendering and can accept a library that ships a new release roughly every two months, with migration notes kept in the wiki rather than in the package. Do not adopt it if you want a scene graph with batteries included, a physics engine, or a component model that manages your application state; three.js gives you a renderer and leaves the rest to you. Before committing, verify three things: that your target browsers support the renderer you picked, since the builds only include WebGL and WebGPU, that the addon you depend on is still present in examples/jsm after your next upgrade, and that your team will actually read the Migration Guide when a release changes an API. If you cannot answer the third one, pin the version and plan the upgrade as scheduled work rather than a background task.

Frequently asked questions

Is three.js worth learning?

It is worth learning if you need to render 3D in a browser and are willing to work with a renderer rather than a full framework. The library is MIT-licensed and the repository is not archived, with releases arriving roughly every two months, so the skill stays current but the API moves.

Is three.js a framework?

No. The README calls it a JavaScript 3D library whose aim is to be easy-to-use, lightweight, cross-browser and general-purpose. It has no opinion about routing, state or component structure, and everything above the renderer is left to you.

How to install three.js?

Install the npm package named three, then import from it. The README's usage example imports the whole namespace and creates a scene, camera, box and WebGLRenderer. To work against the repository itself, the README recommends a shallow clone because the full history is about 2 GB.

How to use three.js in HTML?

The README example appends the renderer's DOM element to document.body and starts an animation loop with renderer.setAnimationLoop. That is the whole integration: one canvas in the page, driven by your own animate function.

How to use three.js in React?

The README does not document a React integration. The package exports a module build for import and addons under ./addons, so any React usage is something you wire yourself around the renderer and its animation loop.

What does three.js mean as a name?

The README does not explain the origin of the name. The package is published as three and the project describes itself as a JavaScript 3D library, which is the only naming detail given.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
Community notes

Community notes