How to Use Draco Compression in Three.js
Loading large 3D meshes in web applications often results in high
bandwidth consumption and sluggish page response times. This article
provides a direct, step-by-step guide on how to integrate Google’s Draco
compression into a Three.js project to drastically reduce GLTF/GLB file
sizes and accelerate asset loading. You will learn how to configure the
DRACOLoader, link it to the GLTFLoader, and
handle the decoder libraries efficiently.
1. Prepare Your Compressed Model
Before writing any code, you must compress your 3D model. When
exporting a GLTF or GLB file from 3D modeling software like Blender, or
when using command-line tools like gltf-pipeline, ensure
that Draco compression is enabled. This packages the
geometric data (vertices, normals, texture coordinates) into a highly
compressed format.
2. Locate the Draco Decoder Files
Because Draco-compressed models cannot be read out of the box by standard parser APIs, Three.js requires a separate WebAssembly (WASM) decoder to unpack the data on the client side.
You need to host these decoder files on your server. You can find
them in your project’s directory under:
node_modules/three/examples/jsm/libs/draco/
Copy the entire draco folder to your public directory
(e.g., /public/draco/ or /assets/draco/).
Alternatively, you can use a verified CDN.
3. Implement the Loaders in JavaScript
To load the model, you must import both GLTFLoader and
DRACOLoader. Instantiate the DRACOLoader,
point it to your decoder files, and then inject it into your
GLTFLoader instance.
Here is the complete implementation code:
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
// Initialize the Three.js scene
const scene = new THREE.Scene();
// 1. Instantiate the DRACOLoader
const dracoLoader = new DRACOLoader();
// 2. Set the path to the folder containing the WASM/JS decoding libraries
// This can be a local path or a CDN URL
dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.5.6/');
// 3. Instantiate the GLTFLoader
const gltfLoader = new GLTFLoader();
// 4. Pass the DRACOLoader instance to the GLTFLoader
gltfLoader.setDRACOLoader(dracoLoader);
// 5. Load your compressed .gltf or .glb model
gltfLoader.load(
'path/to/your/compressed-model.glb',
(gltf) => {
// Add the loaded model to the scene
scene.add(gltf.scene);
// Optional: Release decoding thread memory once loading is finished
dracoLoader.dispose();
},
(xhr) => {
console.log((xhr.loaded / xhr.total * 100) + '% loaded');
},
(error) => {
console.error('An error occurred while loading the model:', error);
}
);4. Important Performance Considerations
While Draco dramatically reduces file transfer sizes, the client’s CPU must spend time decompressing the model once it arrives. For very simple models, the overhead of loading the WASM decoder and decompressing the data might outweigh the network savings. Draco compression is highly recommended for models with complex geometries (high polygon counts) where network transfer is the primary bottleneck.