Idea: update all modules to not import the entire three.js library

I performed a test.

In my Chrome browser, the following loads in about 100 to 200 milliseconds:

		<script type="importmap">
			{
				"imports": {
					"three": "https://unpkg.com/three@^0.139.0/src/Three.js",
					"three/": "https://unpkg.com/three@^0.139.0/"
				}
			}
		</script>

		<script type="module">
			import {Vector3} from 'three/src/math/Vector3.js'
			import {PerspectiveCamera} from 'three/src/cameras/PerspectiveCamera.js'
			import {CameraHelper} from 'three/src/helpers/CameraHelper.js'
			import {TextureLoader} from 'three/src/loaders/TextureLoader.js'
			import {BoxGeometry} from 'three/src/geometries/BoxGeometry.js'
			import {Mesh} from 'three/src/objects/Mesh.js'
			import {AmbientLight} from 'three/src/lights/AmbientLight.js'
		</script>

And the following loads in about 600 to 700 milliseconds:

		<script type="importmap">
			{
				"imports": {
					"three": "https://unpkg.com/three@^0.139.0/src/Three.js",
					"three/": "https://unpkg.com/three@^0.139.0/"
				}
			}
		</script>

		<script type="module">
			import {
				Vector3,
				PerspectiveCamera,
				CameraHelper,
				TextureLoader,
				BoxGeometry,
				Mesh,
				AmbientLight,
			} from 'three'
		</script>

The first one is 3 to 7 times faster.

I measured this in the devtools Network tab.

That is not surprising at all. Your browser doesn’t do tree shaking by itself. As stated numerous times, you need a bundler to take advantage of tree shaking. There is no one size fits all in this discussion.

2 Likes

Yep. I also mentioned that not everyone has a tree shaker.

Yes there is! Direct imports. The best default for all worlds.

Someone with a tree shaker can still optimize beyond that.

then don’t publish. going out without minification, dead code removal, tree shaking, tests & types, img compression, babel polyfills, etc. all you do is hurt your users anyway. this is all 100% automated today, publishing is a non issue.

which still has nothing to do with tree shaking. you will ship tons of unrelated code. the term was coined by rollup making an AST analysis of code that cannot be executed.

This is simply not true and completely depends on your underlying architecture on a server level. For example, if your machine is serving files over HTTP/1.1, then every small file you import is a separate network request (which includes every piece of HTTP-headers/cookies/whatnot bloat) which results in slow initial loading time of your application.

What makes matters worse is caching. Imagine the scenario where your application starts using a new major release of your underlying framework and one of your deeply nested files is using a new (internal) API. What happens if a client caches that (deeply nested) file and your webserver fails to send the appropriate caching headers? Not to mention that not every browser is as compliant as they should be when it comes to caching. Your app would fall apart and because the cache control happens on the client side, there is nothing you can do. The problem isn’t your code but the way you serve it.

This is (also) why bundlers exist. Like @drcmda says; A decent/modern bundler doesn’t simply look at your imports, but analyses the actual code itself, which results in dead-code elimination from your final bundle. You can then minify the bundle and “stamp a version on it”. I know you’re a Typescript enthusiast, so why not bundle your “framework”, minify it and create declaration files that other libraries/apps/frameworks can use?

I don’t know whether you’re working alone or in a larger team, but I can tell you from first hand experience that breaking up your application into individual (standalone) components, and bundle them as such, makes working in/with them in a larger team a lot easier, especially in the long run.