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! 