Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add three/addons (for npm users only) #23368

Closed
wants to merge 8 commits into from

Conversation

marcofugaro
Copy link
Contributor

@marcofugaro marcofugaro commented Jan 28, 2022

Related issue: #23354

Description

With this PR, npm users that rely on bundlers which have tree-shaking built in, will be able to do this:

import * as THREE from 'three';
import { GLTFLoader, OrbitControls } from 'three/addons';

The old examples/jsm imports would still work fine, and nothing is changed on that front.

The main commit is 2d3d558, after that I did some cleaning up in the exports of the examples.

You can test this PR by doing:

npm install three@marcofugaro/three.js#node-addons

@marcofugaro
Copy link
Contributor Author

Fixed some duplicate export conflicts (for example Pass and FullScreenPass are already available in Pass.js), should be all good now.

@CodyJasonBennett
Copy link
Contributor

CodyJasonBennett commented Jan 28, 2022

Seems there's a few side effects that'll have to be ironed out (they break tree-shaking and will run/bundle regardless if you import them).

image

More concerningly, WebGPURenderer emits a side-effect that can break camera math for WebGL (related #20283).

I suppose we can move WebGPURenderer's matrix stuff to its init method as a workaround but these will need a bigger fix.

@marcofugaro
Copy link
Contributor Author

Right.. forgot to check tree-shaking. I'll investigate, thanks for testing!

@mrdoob
Copy link
Owner

mrdoob commented Jan 28, 2022

Actually, if we don't flatten the paths in examples/jsm/addons.js and we rename it to examples/jsm/index.js...

This would work, right?

<script type="importmap">
	{
		"imports": {
			"three": "https://unpkg.com/three@0.137.0/build/three.module.js",
			"three/addons": "https://unpkg.com/three@0.137.0/examples/jsm/"
		}
	}
</script>
    
<script type="module">
      
	import * as THREE from 'three';
	import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
	import { VRButton } from 'three/addons/webxr/VRButton.js';

	...
</script>

Edit: Or I guess it needs to be "three/addons": "https://unpkg.com/three@0.137.0/examples/jsm/index.js"...

@marcofugaro
Copy link
Contributor Author

marcofugaro commented Jan 28, 2022

@mrdoob as of now, you can alias only full paths with import maps 😬

So for this to work:

import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

you would have to add as import map the full path meaning three/addons/loaders/GLTFLoader.js.

wrong, see #23368 (comment)

@marcofugaro
Copy link
Contributor Author

Also we can't use examples/jsm/addons.js on the browser because it would import every module 😂

@mrdoob
Copy link
Owner

mrdoob commented Jan 28, 2022

lol

@mrdoob
Copy link
Owner

mrdoob commented Jan 28, 2022

This works~! ✨

<script type="importmap">
	{
		"imports": {
			"three": "https://unpkg.com/three@0.137.0/build/three.module.js",
			"three-addons/": "https://unpkg.com/three@0.137.0/examples/jsm/"
		}
	}
</script>
    
<script type="module">
      
	import * as THREE from 'three';
	import { GLTFLoader } from 'three-addons/loaders/GLTFLoader.js';
	import { VRButton } from 'three-addons/webxr/VRButton.js';

	...
</script>

https://github.com/WICG/import-maps#packages-via-trailing-slashes

(Thanks to Russell Bicknell and Justin Ridgewell for the pointers! 🙏)

@mrdoob
Copy link
Owner

mrdoob commented Jan 28, 2022

So I guess we do not need this PR?

We'll have to make another script to implement that pattern in all the examples though.

@CodyJasonBennett
Copy link
Contributor

CodyJasonBennett commented Jan 28, 2022

Maybe, but it also exposed some potential issues for users regarding the chevrotain module and WebGPURenderer (the latter being a bit more concerning).

Is there still an issue to track tree-shaking? WebGPURenderer can break some apps as-is if ever bundled alongside WebGLRenderer despite the workaround though.

@mrdoob
Copy link
Owner

mrdoob commented Jan 28, 2022

Is there still an issue to track tree-shaking?

Maybe better creating new issues for these.

@marcofugaro
Copy link
Contributor Author

marcofugaro commented Jan 28, 2022

After a bit of digging, it looks like rollup correctly tree-shakes all unused files, while webpack and esbuild have difficulty tree-shaking the following files:

List of unshaken files (excluding webgpu + nodes)
node_modules/three/examples/jsm/animation/CCDIKSolver.js
node_modules/three/examples/jsm/animation/MMDPhysics.js
node_modules/three/examples/jsm/animation/MMDAnimationHelper.js
node_modules/three/examples/jsm/shaders/BokehShader2.js
node_modules/three/examples/jsm/controls/FirstPersonControls.js
node_modules/three/examples/jsm/controls/TransformControls.js
node_modules/three/examples/jsm/controls/DragControls.js
node_modules/three/examples/jsm/controls/PointerLockControls.js
node_modules/three/examples/jsm/controls/ArcballControls.js
node_modules/three/examples/jsm/controls/OrbitControls.js
node_modules/three/examples/jsm/csm/CSMFrustum.js
node_modules/three/examples/jsm/csm/CSMShader.js
node_modules/three/examples/jsm/csm/CSM.js
node_modules/three/examples/jsm/deprecated/Geometry.js
node_modules/three/examples/jsm/exporters/GLTFExporter.js
node_modules/three/examples/jsm/libs/fflate.module.js
node_modules/three/examples/jsm/exporters/DRACOExporter.js
node_modules/three/examples/jsm/libs/mmdparser.module.js
node_modules/three/examples/jsm/geometries/ParametricGeometry.js
node_modules/three/examples/jsm/geometries/ParametricGeometries.
node_modules/three/examples/jsm/math/ConvexHull.js
node_modules/three/examples/jsm/math/SimplexNoise.js
node_modules/three/examples/jsm/geometries/LightningStrike.js
node_modules/three/examples/jsm/geometries/RoundedBoxGeometry.js
node_modules/three/examples/jsm/helpers/VertexTangentsHelper.js
node_modules/three/examples/jsm/helpers/VertexNormalsHelper.js
node_modules/three/examples/jsm/interactive/InteractiveGroup.js
node_modules/three/examples/jsm/interactive/SelectionBox.js
node_modules/three/examples/jsm/lines/LineSegmentsGeometry.js
node_modules/three/examples/jsm/lines/LineGeometry.js
node_modules/three/examples/jsm/lines/LineMaterial.js
node_modules/three/examples/jsm/lines/Wireframe.js
node_modules/three/examples/jsm/lines/WireframeGeometry2.js
node_modules/three/examples/jsm/lines/LineSegments2.js
node_modules/three/examples/jsm/lines/Line2.js
node_modules/three/examples/jsm/loaders/FBXLoader.js
node_modules/three/examples/jsm/misc/VolumeSlice.js
node_modules/three/examples/jsm/misc/Volume.js
node_modules/three/examples/jsm/loaders/ifc/web-ifc-api.js
node_modules/three/examples/jsm/loaders/FontLoader.js
node_modules/three/examples/jsm/loaders/GLTFLoader.js
node_modules/three/examples/jsm/libs/chevrotain.module.min.js
node_modules/three/examples/jsm/loaders/VRMLLoader.js
node_modules/three/examples/jsm/utils/WorkerPool.js
node_modules/three/examples/jsm/loaders/KTX2Loader.js
node_modules/three/examples/jsm/loaders/LogLuvLoader.js
node_modules/three/examples/jsm/libs/opentype.module.min.js
node_modules/three/examples/jsm/loaders/BasisTextureLoader.js
node_modules/three/examples/jsm/loaders/LDrawLoader.js
node_modules/three/examples/jsm/loaders/lwo/LWO2Parser.js
node_modules/three/examples/jsm/loaders/lwo/LWO3Parser.js
node_modules/three/examples/jsm/loaders/lwo/IFFParser.js
node_modules/three/examples/jsm/loaders/OBJLoader.js
node_modules/three/examples/jsm/shaders/MMDToonShader.js
node_modules/three/examples/jsm/loaders/MMDLoader.js
node_modules/three/examples/jsm/loaders/KTXLoader.js
node_modules/three/examples/jsm/loaders/RGBMLoader.js
node_modules/three/examples/jsm/loaders/PLYLoader.js
node_modules/three/examples/jsm/objects/Lensflare.js
node_modules/three/examples/jsm/objects/MarchingCubes.js
node_modules/three/examples/jsm/objects/LightningStorm.js
node_modules/three/examples/jsm/objects/Reflector.js
node_modules/three/examples/jsm/objects/ReflectorForSSRPass.js
node_modules/three/examples/jsm/objects/Refractor.js
node_modules/three/examples/jsm/objects/ShadowMesh.js
node_modules/three/examples/jsm/objects/Sky.js
node_modules/three/examples/jsm/objects/Water.js
node_modules/three/examples/jsm/objects/Water2.js
node_modules/three/examples/jsm/math/MeshSurfaceSampler.js
node_modules/three/examples/jsm/math/OBB.js
node_modules/three/examples/jsm/math/Capsule.js
node_modules/three/examples/jsm/math/ImprovedNoise.js
node_modules/three/examples/jsm/math/Octree.js
node_modules/three/examples/jsm/math/Lut.js
node_modules/three/examples/jsm/misc/ConvexObjectBreaker.js
node_modules/three/examples/jsm/misc/Gyroscope.js
node_modules/three/examples/jsm/modifiers/CurveModifier.js
node_modules/three/examples/jsm/modifiers/SimplifyModifier.js
node_modules/three/examples/jsm/modifiers/EdgeSplitModifier.js
node_modules/three/examples/jsm/libs/OimoPhysics/OimoPhysics.js
node_modules/three/examples/jsm/libs/OimoPhysics/index.js
node_modules/three/examples/jsm/postprocessing/Pass.js
node_modules/three/examples/jsm/shaders/HalftoneShader.js
node_modules/three/examples/jsm/shaders/SMAAShader.js
node_modules/three/examples/jsm/shaders/CopyShader.js
node_modules/three/examples/jsm/postprocessing/OutlinePass.js
node_modules/three/examples/jsm/shaders/SSAOShader.js
node_modules/three/examples/jsm/postprocessing/SSAOPass.js
node_modules/three/examples/jsm/shaders/SSRrShader.js
node_modules/three/examples/jsm/postprocessing/SSRrPass.js
node_modules/three/examples/jsm/shaders/LuminosityHighPassShader.
node_modules/three/examples/jsm/postprocessing/UnrealBloomPass.js
node_modules/three/examples/jsm/shaders/SAOShader.js
node_modules/three/examples/jsm/shaders/DepthLimitedBlurShader.js
node_modules/three/examples/jsm/shaders/UnpackDepthRGBAShader.js
node_modules/three/examples/jsm/postprocessing/SAOPass.js
node_modules/three/examples/jsm/shaders/DotScreenShader.js
node_modules/three/examples/jsm/shaders/SSRShader.js
node_modules/three/examples/jsm/postprocessing/SSRPass.js
node_modules/three/examples/jsm/shaders/ConvolutionShader.js
node_modules/three/examples/jsm/postprocessing/BloomPass.js
node_modules/three/examples/jsm/renderers/CSS2DRenderer.js
node_modules/three/examples/jsm/renderers/CSS3DRenderer.js
node_modules/three/examples/jsm/renderers/SVGRenderer.js
node_modules/three/examples/jsm/libs/flow.module.js
node_modules/three/examples/jsm/shaders/GodRaysShader.js
node_modules/three/examples/jsm/shaders/VerticalBlurShader.js
node_modules/three/examples/jsm/shaders/ColorCorrectionShader.js
node_modules/three/examples/jsm/shaders/TriangleBlurShader.js
node_modules/three/examples/jsm/shaders/FXAAShader.js
node_modules/three/examples/jsm/shaders/
node_modules/three/examples/jsm/shaders/ToonShader.js
node_modules/three/examples/jsm/shaders/NormalMapShader.js
node_modules/three/examples/jsm/shaders/FreiChenShader.js
node_modules/three/examples/jsm/shaders/VolumeShader.js
node_modules/three/examples/jsm/shaders/
node_modules/three/examples/jsm/shaders/VerticalTiltShiftShader.
node_modules/three/examples/jsm/shaders/SobelOperatorShader.js
node_modules/three/examples/jsm/shaders/HorizontalBlurShader.js
node_modules/three/examples/jsm/shaders/ColorifyShader.js
node_modules/three/examples/jsm/libs/stats.module.js
node_modules/three/examples/jsm/utils/GPUStatsPanel.js
node_modules/three/examples/jsm/webxr/XRHandPrimitiveModel.js
node_modules/three/examples/jsm/libs/motion-controllers.module.js
node_modules/three/examples/jsm/webxr/OculusHandPointerModel.js
node_modules/three/examples/jsm/webxr/VRButton.js

If you want to dig into it more, here is the resulting esbuild bundle: addons-esbuild.js.zip

Most of them are unshaken because of the missing /* @__PURE__ */ notation on variables, while other because of various side-effects.

@marcofugaro
Copy link
Contributor Author

I am going to close this PR for now since I don't have the bandwitdth to solve the tree-shaking problems in all these files.

We'll go with the pattern proposed by @mrdoob, best part is that it would be exactly the same both on node and the browser 💪

import * as THREE from 'three';
import { GLTFLoader } from 'three-addons/loaders/GLTFLoader.js';
import { VRButton } from 'three-addons/webxr/VRButton.js';

I'll make a PR sometime next week.

@donmccurdy
Copy link
Collaborator

Is "three-addons" a new npm package, or just an alias used for examples in an import map here?

@CodyJasonBennett
Copy link
Contributor

An alias but it can be a bit misleading indeed.

@marcofugaro
Copy link
Contributor Author

Is "three-addons" a new npm package, or just an alias used for examples in an import map here?

Right.. we probably want this, to avoid confusion

import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { VRButton } from 'three/addons/webxr/VRButton.js';

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.

4 participants