rollup-plugin-three-minify
v1.0.2
Published
Minify Three.js shader code, and remove redundant code
Maintainers
Readme
rollup-plugin-three-minify
This plugin reduces the bundle size of applications using Three.js by:
- Removing redundant
WebGLRenderersubsystems - Removing redundant materials from
ShaderLib - Removing redundant shaders from
ShaderChunk - Minifies GLSL code by removing redundant whitespace and mangling identifiers
[!NOTE] This plugin is backwards-compatible with Three.js revisions down to 135. It might work with earlier revisions but I will not guarantee that.
Rationale
- JavaScript minification tools like terser will not minify the contents of string literals such as GLSL code. This plugin however will minify the Three.js GLSL code used by your application, and remove any unused GLSL code.
- The
WebGLRendererclass includes many optional subsystems which are never removed by tree-shaking. This plugin will determine the necessary subsystems based on your options and replace any unused subsystems with no-op stubs.
[!WARNING] By default, this plugin behaves as a whitelist and will remove ALL GLSL code and optional subsystems. You must specify exactly which features and materials your application requires, and everything else will be removed.
Install
npm install three rollup-plugin-three-minifyUsage
Add this plugin to the start of your bundler plugins array:
// rollup.config.js / rolldown.config.js
import threeMinifyPlugin from 'rollup-plugin-three-minify';
export default {
input: 'index.js',
plugins: [
threeMinifyPlugin(),
// Other plugins...
],
};// vite.config.js
import { defineConfig } from 'vite';
import threeMinifyPlugin from 'rollup-plugin-three-minify';
export default defineConfig({
plugins: [
{
...threeMinifyPlugin(),
// Only minify Three.js on `build` phase!
apply: 'build',
},
// Other plugins...
],
});Usage Example
Import three and build your application as you normally would:
// index.js (entry file)
import * as THREE from 'three';
const scene = new THREE.Scene();
const mesh = new THREE.Mesh(
new THREE.TorusKnotGeometry(),
new THREE.MeshBasicMaterial(),
);
scene.add(mesh);
const camera = new THREE.PerspectiveCamera();
camera.position.setZ(-4);
camera.lookAt(mesh.position);
const renderer = new THREE.WebGLRenderer();
renderer.render(scene, camera);
document.body.appendChild(renderer.domElement);This basic example only uses MeshBasicMaterial and no other features, so your plugin configuration should look like this:
// rollup.config.js
import threeMinifyPlugin from 'rollup-plugin-three-minify';
export default {
input: 'index.js',
plugins: [
threeMinifyPlugin({
materials: 'basic',
}),
],
};This Rollup configuration will remove all shaders and subsystems that are not required by MeshBasicMaterial. If you need to use other features like textures or shadows then you must specify that in the options object!
Options
colorKeywords
- Type:
boolean - Default:
false
Three.js contains an object called colorKeywords which maps CSS color names (see named-color) to color values, so you can create colors with CSS color names.
Set this option to true if your application will create colors by name.
// index.js
import { Color } from 'three';
const red: Color = new Color('red');
const hex: string = red.getHexString(); // "ff0000"// rollup.config.js
import threeMinifyPlugin from 'rollup-plugin-three-minify';
export default {
input: 'index.js',
plugins: [
threeMinifyPlugin({
colorKeywords: true,
}),
],
};jsonMethods
- Type:
boolean - Default:
false
Many classes in Three.js include a toJSON() method which is used to safely serialize its data. Some classes also have a fromJSON() method which is used to reverse the serialization. These methods are analogous to JSON.stringify() and JSON.parse().
Set this option to true if your application will use these JSON methods.
// index.js
import { Sphere } from 'three';
const data: string = JSON.stringify(new Sphere()); // calls `Sphere.toJSON()`
const test: Sphere = new Sphere().fromJSON(data);// rollup.config.js
import threeMinifyPlugin from 'rollup-plugin-three-minify';
export default {
input: 'index.js',
plugins: [
threeMinifyPlugin({
jsonMethods: true,
}),
],
};xr
- Type:
boolean - Default:
false
The WebGLRenderer class includes a subsystem called WebXRManager which is responsible for managing XR stuff (like virtual reality).
Set this option to true if you are building an XR application.
// index.js
import { WebGLRenderer } from 'three';
const renderer = new WebGLRenderer();
renderer.xr.enabled = true;// rollup.config.js
import threeMinifyPlugin from 'rollup-plugin-three-minify';
export default {
input: 'index.js',
plugins: [
threeMinifyPlugin({
xr: true,
}),
],
};materials
- Type:
MaterialName | MaterialName[] - Default:
[]
Three.js material(s) to keep in the bundle (whitelist)
[!NOTE] Every material (except
RawShaderMaterial) requires a specific set ofincludesto render, otherwise the renderer will crash.This plugin will keep only the necessary
includesfor each material in this option. Some optional material features will not work unless you specify them in thefeaturesoption.
|MaterialName|Usage|
|--|--|
|background|"Flat" textures on Scene.background|
|backgroundCube|Cube or Equirectangular textures on Scene.background (since revision ≥146)|
|cube|Same as backgroundCube (for revisions <146)|
|depth|MeshDepthMaterial|
|distance|MeshDistanceMaterial (since revision ≥182)|
|distanceRGBA|Same as distance (for revisions <182)|
|dashed|LineDashedMaterial|
|basic|LineBasicMaterial or MeshBasicMaterial|
|lambert|MeshLambertMaterial|
|matcap|MeshMatcapMaterial|
|normal|MeshNormalMaterial|
|phong|MeshPhongMaterial|
|standard|MeshStandardMaterial|
|physical|MeshPhysicalMaterial|
|toon|MeshToonMaterial|
|points|PointsMaterial|
|shadow|ShadowMaterial|
|sprite|SpriteMaterial|
features
- Type:
FeatureName | FeatureName[] - Default:
[]
Three.js feature(s) to keep in the bundle (whitelist)
[!NOTE] Each "feature" refers to a group of interdependent
includesand is thus a safer way to define the requirements of your application.
Check this handy Material Feature compatibility table
|FeatureName|Usage|
|--|--|
|alphahash|Material.alphaHash (since revision ≥154)|
|alphamap|Material.alphaMap|
|alphatest|Material.alphaTest|
|aomap|Material.aoMap|
|batching|BatchedMesh (since revision ≥159)|
|bumpmap|Material.bumpMap|
|clipping|Material.clippingPlanes (or WebGLRenderer.clippingPlanes)|
|colors|Material.vertexColors|
|colorspace|Automatically included by all materials (except RawShaderMaterial)|
|displacementmap|Material.displacementMap|
|dithering|Material.dithering|
|emissivemap|Material.emissiveMap|
|envmap|Material.envMap (or Scene.environment)|
|fog|Scene.fog|
|iridescence|Material.iridescence (since revision ≥141)|
|lightmap|Material.lightMap|
|lights|For any shader which responds to lights[1]|
|logdepthbuf|Renderer.logarithmicDepthBuffer|
|map|Material.map|
|metalnessmap|Material.metalnessMap|
|morphtargets|BufferGeometry.morphAttributes|
|normalmap|Material.normalMap|
|normals|For any shader which uses the normal geometry attribute[1]|
|roughnessmap|Material.roughnessMap|
|shadows|Renderer.shadowMap.enabled|
|skinning|SkinnedMesh|
|specularmap|Material.specularMap|
|tonemapping|Renderer.toneMapping|
|transmission|Material.transmission|
|vertices|For any shader which uses the position geometry attribute[1]|
[1] This feature is automatically included by applicable Three.js materials, so exists only as convenience for authoring custom shaders.
includes
- Type:
IncludeName | IncludeName[] - Default:
[]
Three.js include(s) to keep in the bundle (whitelist)
[!NOTE] I use the word "include" to mean keys of
ShaderChunk, because they correlate to pieces of GLSL code which are injected via#include <xyz>directives at runtime byWebGLProgram.Most
includesrequire other "sibling"includesto function properly, therefore it is recommended to use thefeaturesoption instead for convenience, but you can also use this option for more precise control.
Please check your ShaderChunk source code for a full list of all "includes" relevant to your revision of Three.js:
.../node_modules/three/src/renderers/shaders/ShaderChunktextures
- Type:
boolean - Default:
false
The WebGLRenderer class uses a subsystem called WebGLTextures which is responsible for managing textures.
Set this option to true if your application uses textures in ways that cannot be inferred by your selection of materials or features (for example, if your application uses render targets or custom shaders).
debug
- Type:
boolean - Default:
false
Useful in development (should be disabled in production)
When enabled, pruned subsystems will emit a warning if used and explain how to change the plugin configuration to include the subsystem.
// index.js
import { WebGLRenderer } from 'three';
const renderer = new WebGLRenderer();
// Clipping planes will not work because the "clipping" feature is omitted.
// Debug mode is enabled, so the `WebGLClipping` stub will emit a warning.
renderer.localClippingEnabled = true;// rollup.config.js
import threeMinifyPlugin from 'rollup-plugin-three-minify';
export default {
input: 'index.js',
plugins: [
threeMinifyPlugin({
debug: true,
}),
],
};