Hi!
I just want to share our experience with treeshaking a project using three and GSAP. We’re bundling with Rollup and our solution at the moment sounds somewhat similar to what @yushijinhun’s plugin is supposed to do, but still a bit different:
-
rollup treeshake:
addtreeshake: { moduleSideEffects: false }
to Rollup config. If this is not done GSAP and THREE will be fully added including all modules and plugins even if you just import / use one of them (notice: this will happen with all namespaced libraries like ‘three’ or ‘gsap’). See rollup treeshake docs -
three as npm dependency:
import { Foo } from 'three'
, means from'node_modules/three/build/three.module.js'
does NOT treeshake, you have to import from'src'
: e.g.import { Foo } from '../../node_modules/three/src/Three'
. To achieve this easily we writefrom 'three'
in our code and use the @rollup/plugin-alias to replace all'three'
entries accordingly when bundling, like this:
plugins: [
alias({
entries: [
{
find: 'three',
replacement: __dirname + '/node_modules/three/src/Three'
}
],
})
]
The above method works / treeshakes perfectly if you use modules from inside 'three/src'
folder ONLY. As soon as you import something from the 'three/examples'
folder, e.g. 'import { Foo } from '../../node_modules/three/examples/jsm/loaders/Foo'
, full three is going to be added to the bundle ADDITIONALLY because (as it seems) modules inside 'three/examples/jsm'
import from 'three/build/three.module.js'
. I’m not quite sure why exactly this is happening, but we’ve found a solution (not sure if best) which works:
At the moment we only need the GLTFLoader and the DRACOLoader both inside 'three/examples/jsm/loaders'
. We copied them to the 'three/src/loaders'
and changed the imports inside them accordingly + added corresponding exports to 'three/src/Three.js'
& 'three/src/Three.d.ts'
. See here Move GLTF & DRACO Loaders from 'examples' to 'src' · cream-gmbh/three-116-1@9c2b1d3 · GitHub
This way the Loaders get also treeshaked & we get the smallest possible bundle size, I guess… well, let’s say I’m pretty sure. check out https://cream.gmbh/ to see what I’m talking about (bundle size 840 KB / 273 KB gzipped incl. three, gsap, svelte & website-engine / animations). (notice: GLTFLoader is importing A LOT of modules, so without it, the bundle size would be even smaller.)
I’m not sure though if this is the best, most elegant way to do this , means maybe there are some other Rollup config tweaks we didn’t figure out by now + this way any 'three/examples/jsm'
-modules you might need would have to be copied and changed like the both Loaders mentioned above.
I hope this helps & please feel free to correct me / propose a better solution!