Making 'three' tree-shakeable
See original GitHub issueThe goal with tree-shaking here is I should be able to import a class from 'three'
, and only get the classes needed. In my test bundle importing only Vector2
is producing a 295 KB (uncompressed) file still with lots of remaining side-effects even after r141
and all the work done on #24006 (down from a 1 MB bundle in r140
).
I’m opening this issue to resolve the remaining side-effects, which is do-able with some more work, and we have a couple ways of testing that.
Also to make the claim that 'three'
is finally fully tree-shakeable, we’ll need to verify that in the most popular bundlers. I’ll start with Rollup, Webpack, Parcel and esbuild. Open to suggestions of other bundlers and configurations, and will start with a simple test of importing only Vector2
.
Steps to reproduce the behavior:
import { Vector2 } from 'three';
console.log(new Vector2(0, 1));
And with agadoo:
npx agadoo
...
Failed to tree-shake build/three.module.js
It’s worth noting that importing from the source files with agadoo
also fails, and is something I can look into as well.
npx agadoo src/Three.js
...
Failed to tree-shake src/Three.js
The expected behavior, regardless of agadoo
, is simply looking at the output bundle. If I import Vector2
, I’m expecting only the @license
header comment, and Vector2
, nothing else.
References:
Issue Analytics
- State:
- Created a year ago
- Reactions:7
- Comments:122 (87 by maintainers)
Top GitHub Comments
Should we close this then?
Alright, so I’ve spent some more time tonight with the latest, here’s a summary of my findings. 😉
src/Three.js
itself has side-effects at the bottom because of the checks for__THREE_DEVTOOLS__
and multiple instances. #24225Three.Legacy.js
is fully tree-shakable now, nice work guys! 🎉 #24006DataUtils.js
file has a number of expressions and for loops causing side-effects. #24218PropertyBinding.js
,KeyframeTrack.js
,Materials.js
,Material.js
,Object3D.js
,Euler.js
,Texture.js
andColor.js
files have static and prototype properties that could be converted to class fields. Have we made a decision on the use of class fields?Material.js
has a side-effect at the bottom withMaterial.fromType
and a// TODO: Behavior added in Materials.js
, can that be removed? #24094ShaderLib.js
,UniformsLib.js
andShaderChunk.js
are also side-effects, perhaps there’s a different approach we could take with defining these shaders? #24221ObjectLoader.js
creates a big side-effect with theGeometries
namespace, removing that one line allows for tree-shaking.WebGLRenderer.js
of-course is loading a lot of classes including the shader classes with side-effects, which in-turn creates a domino effect importing all the classes fromShaderLib.js
andUniformsLib.js
, etc., removing those classes allows for tree-shaking as well.MathUtils.js
has a side-effect at the top with the_lut
for loop. #24210Removing all of the above, shader and renderer classes from
src/Three.js
is allowing me to build a module bundle withnpm run build-module
and then in-turn import frombuild/three.module.js
side-effect free.Still lots of work to do but we’re getting there! 😅