Enable tree-shaking both for the main and examples files#16301
Enable tree-shaking both for the main and examples files#16301marcofugaro wants to merge 4 commits intomrdoob:devfrom marcofugaro:dev
Conversation
| @@ -7,6 +7,7 @@ | |||
| "jsnext:main": "build/three.module.js", | |||
| "module": "build/three.module.js", | |||
There was a problem hiding this comment.
It'll be a problem if the module entry is build/three.module.js but the JSM example files all import from src/Three.js. In this case...
import { Vector3 } from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';... GLTFLoader will create Vector3 instances that are not the same as the Vector3 instances from three.
There was a problem hiding this comment.
Nice catch!
My objective was to find a solution for people who already import the main three.js from the src/ folder for the tree-shaking to take effect, like this:
import { Vector3 } from 'three/src/math/Vector3';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';Currently if they do that for the examples/jsm the whole bundle will be imported as well.
Is there a way we can achieve this in your opinion?
|
In #16220 we're considering converting the examples to use However if we do this while importing from |
|
@looeee I didn't know about those plans, you're right, three.js needs to be imported as a bundle in the esmodules examples. So how would we go about importing
without importing the whole bundle like we do with
|
|
Hmm, I can't think of any easy way around this right now. We either get easy tree-shaking (but Webpack only, I think?), or we get to convert the examples to use I'm inclined to think that converting the examples is more important, and it's up to people to get tree-shaking working in their own apps. They would need to do this: import { Vector3 } from 'three/src/math/Vector3'; // from NPM package
import { OrbitControls } from './local_dir/OrbitControls.js';Then in the local copy of import {
EventDispatcher,
MOUSE,
Quaternion,
Spherical,
Vector2,
Vector3
} from "../../../build/three.module.js";to import from the various |
|
You're right, webpack should tree-shake the I'll make a separate PR for the |
Happy easter everyone!
The aim of this PR is to optimize the repo in order to enable tree-shaking for the webpack users so all of the non-necessary three.js code isn't included in the final bundle.
All the heavy work is done by the property
"sideEffects": falsein the package.json, which is saying there isn't any shared "state" in three.js which is affected by other non-required files. This is true since three.js' core uses only import/exports and isn't using any non-imported module (correct me if I'm wrong).More info here
With this, importing any component from the main
Three.jsfile won't include all of the non-executed components in the bundle anymore, for exampleBefore:
After:
Even better importing three.js
* as THREEwill still be tree-shaked and include in the bundle only the properties which you use in the code:Becomes:
Here is a test-repo if you want to test this out: three-test.zip
For the
examples/jsmfiles instead, I updated the imports from"../../../build/three.module.js"to"../../../src/Three.js", the tree-shaking takes care of the rest. This is because the filethree.module.jscannot be tree-shaken since all the code is in the same file. (If anyone has more insight on this please share)Here is a test:
Before:
After:
Finally I added
"prepublishOnly": "node utils/modularize.js"to the package.json just to make sure the jsmodules are always up-to-date.