Skip to content

Allow tree-shaking by adding "sideEffects": false flag#16317

Closed
marcofugaro wants to merge 1 commit intomrdoob:devfrom
marcofugaro:side-effects
Closed

Allow tree-shaking by adding "sideEffects": false flag#16317
marcofugaro wants to merge 1 commit intomrdoob:devfrom
marcofugaro:side-effects

Conversation

@marcofugaro
Copy link
Copy Markdown
Contributor

This PR adds the flag "sideEffects": false in the package.json, with the objective to allow tree-shaking for webpack users. More precisely this will allow people to do

import * as THREE from 'three/src/Three'

while including only the components which are actually used in the code in the bundle.

Example

import * as THREE from 'three/src/Three'
console.log(THREE.Vector3)
  Asset    Size  
main.js  15 KiB

Setting sideEffects to false means there isn't any shared "state" in three.js which is affected by other non-required files (side effects). 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, don't know 100% of three.js' core).

More info here

@gkjohnson
Copy link
Copy Markdown
Collaborator

Why does the src/Three file need to be imported? My understanding of tree-shaking from the rollup documentation that it doesn't require anything to be in separate files. Is that not the case?

And I'm not sure if I agree that we should encourage importing the source file directly. I'm also not sure how this will work with plugins that try to import the existing three.js examples such as the @wildpeaks/three-webpack-plugin or when importing the new jsm ones. Have you given that a try?

@marcofugaro
Copy link
Copy Markdown
Contributor Author

Yes, if enabled with the sideEffects flag, tree-shaking would work even with the single file build/three.module.js. However the problem with that file is that tree-shaking doesn't work on stuff that is being modified in place, such as

function Vector3 () {
  // ...
}

Objec.assign(Vector3.prototype, {
  set: function() {}
  // ...
})

which is the structure of the entire codebase of three.js.
So until we don't rewrite everything with classes, tree-shaking for the main bundle won't work.
Instead it works fine with the file src/Three.js because it has only import/exports in it.

It's not encouraged but many people area already doing it. It's for people who know what they're doing.

Regarding the jsm, they would be a problem, since they import from the three.module.js. If you import from the src/ and build/, the code would be duplicated.

@mrdoob
Copy link
Copy Markdown
Owner

mrdoob commented May 1, 2019

It's for people who know what they're doing.

Sounds like this would potentially bring confusion to a lot of users then?

@looeee
Copy link
Copy Markdown
Contributor

looeee commented May 1, 2019

TBH I think the right approach here is to change the library so that it works with tree-shaking. We should only recommend that people import from build/, not from src/.

@marcofugaro is it correct that if we change this style:

function Vector3 ( x, y, z ) {
  ...
}

Objec.assign(Vector3.prototype, {
  set: function() {}
  ...
})

to

class Vector3 {
   constructor( x, y, z ) { ... }

   set( x, y, z ) { ... }
   ...
}

then tree-shaking will work?

Class support is higher than script type="module", but again we lose IE11 support. However, people can run their code through Babel to get that support in their apps if they need it.

@marcofugaro
Copy link
Copy Markdown
Contributor Author

@mrdoob hmmm, alright.

@looeee yup, classes + sideEffects flag would work, I have tested it.

@mrdoob
Copy link
Copy Markdown
Owner

mrdoob commented May 2, 2019

Closing this for now.

@mrdoob mrdoob closed this May 2, 2019
@looeee
Copy link
Copy Markdown
Contributor

looeee commented May 2, 2019

@marcofugaro there's already discussion of adopting ES6 classes in #11552, so if you want to continue this conversation please do so there.

We're proceeding step by step with adopting ES6 features, and the current focus is on converting examples/js to modules in examples/jsm. Next in line after that is adopting script type="module" in the examples (these can probably be done concurrently).

Once these are done, we can move on to the next step. IMO making tree-shaking work should be given the highest priority.

@hlehmann
Copy link
Copy Markdown

Still webpack checks if there is sideEffects: false.

Then you can still import * as three from "three" and it will tree shake from build/three.module.js

@mrdoob
Copy link
Copy Markdown
Owner

mrdoob commented Feb 20, 2021

Decided to give it a go: #21313

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants