Skip to content

Three.js dev iteration process, bundling has become really slow #30829

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

Open
gkjohnson opened this issue Mar 31, 2025 · 17 comments · May be fixed by #30851 or #30865
Open

Three.js dev iteration process, bundling has become really slow #30829

gkjohnson opened this issue Mar 31, 2025 · 17 comments · May be fixed by #30851 or #30865
Milestone

Comments

@gkjohnson
Copy link
Collaborator

Description

I'm not exactly sure when it happened but modifying three.js core and checking the changes in the example files has become really difficult. The changes used to be reflected almost immediately but now it takes several seconds for anything to change resulting in a lack of trust around whether the latest changes are being displayed. And even then once the page does change it initially logs an error that a subfile is not yet available (because it's still being built):

Uncaught SyntaxError: The requested module './three.core.js' does not provide an export named 'UniformsUtils' (at three.module.js:6:1049)

I suspect this is because with WebGPU and TSL there have become 6 build targets that are also built even if not needed during dev.

Solution

  • Produce a separate "dev" rollup config that builds what's necessary focused on iteration speed, removing code splitting, multiple build targets.
  • Possibly produce a separate dev command for WebGPURenderer and WebGLRenderer if speed continues to be a problem to minimize files being built.
  • Import three.js directly from source during development so no build is required.

Alternatives

  • Switch to another, faster build process.
  • Tolerate unnecessary build delay, lack of trust in dev bundle process.

Additional context

No response

@gkjohnson gkjohnson added this to the r176 milestone Mar 31, 2025
@gkjohnson gkjohnson changed the title Three.js dev process has become really slow Three.js dev iteration process, bundling has become really slow Mar 31, 2025
@RenaudRohlinger
Copy link
Collaborator

What I do is that I just replace the build path by src and then I get realtime dev environment:

<script type="importmap">
{
	"imports": {
		"three": "../src/Three.WebGPU.js",
		"three/webgpu": "../src/Three.WebGPU.js",
		"three/tsl": "../src/Three.TSL.js",
		"three/addons/": "./jsm/",
	}
}
</script>

@gkjohnson
Copy link
Collaborator Author

I understand there are ad-hoc patches that can be made but we should fix the dev process so it's not so misleading, slow, and error prone for non power users.

@donmccurdy
Copy link
Collaborator

donmccurdy commented Mar 31, 2025

Just to make sure we're all seeing similar numbers – time npm run build takes 6–8s for me on an M1 Pro CPU, are you seeing comparable times, give or take any CPU differences?

npm run build 22.19s user 1.41s system 334% cpu 7.053 total

@donmccurdy
Copy link
Collaborator

Commenting out the minified builds drops the build time to a pretty consistent 2–2.5s, for me, perhaps we could make that the default and only do minification for production builds. Nervous to disable code splitting, since that might hide mistakes when importing from the wrong place. Using source files in local development could be nice but probably means we can't just use a simple static server anymore.

@Mugen87
Copy link
Collaborator

Mugen87 commented Mar 31, 2025

MacMini with M2Pro:

Image

@Mugen87
Copy link
Collaborator

Mugen87 commented Mar 31, 2025

IMO, these numbers are okay. Especially since the files used in the examples are build first. I'm not sure this justifies a change in the build system...

@WestLangley
Copy link
Collaborator

I use npm run build-module. Thank you for adding that.

npm run build-module 10.77s user 0.80s system 255% cpu 4.523 total

@gkjohnson
Copy link
Collaborator Author

gkjohnson commented Mar 31, 2025

Here's how long it takes for a build to run for me - similar numbers it looks like:

npm run build 23.14s user 1.29s system 295% cpu 8.266 total

By comparison I'm getting around 7-8 seconds for a build in r150 so the build times have more than tripled:

npm run build 7.77s user 0.54s system 204% cpu 4.054 total


IMO, these numbers are okay. Especially since the files used in the examples are build first. I'm not sure this justifies a change in the build system...

I'm not sure how you're concluding this. I'm not convinced that the "files used in the examples are build first" since the "three.core.js" file is used by the import from examples and possibly rebuilt multiple times or something. The current time from change to see the changes in the examples is unacceptable and you don't need to look at numbers to experience that dev has gotten worse. Are you not seeing a significantly degraded dev experience? The fact that users are modifying the example import maps to point to source rather than build to test files is evidence it's not just me.

More subjectively here's what the dev experience feels like in the dev branch right now:

  1. Make a change to the "ExtrudeGeometry" file such as adding a console log.
  2. Quickly switch to a browser with "webgl_geometry_text" open and refresh the page.
  3. Refresh the page 10 to 20 times before the changes you made are available. During that time the page logs the error './three.core.js' does not provide an export named 'UniformsUtils' for a portion of the refreshes. The remaining refreshes all misleadingly load the example page as expected without the changes made.

Compare to r150:

  1. Make a change to the "ExtrudeGeometry" file such as adding a console log.
  2. Quickly switch to a browser with "webgl_geometry_text" open and refresh the page.
  3. Refresh the page 1-4 times before the changes are available.

I've already made the mistake of thinking changes I made were present and wasted time testing something only to realize the I was looking at old code multiple times.

@Makio64
Copy link
Contributor

Makio64 commented Apr 1, 2025

M3 Pro Max :
build once
Image

When I change for example PlaneGeometry :
Image

I rarely use the examples from the lib directly to test my changes, but it's indeed feeling very slow and no hotreload as well.
I also had time to press f5 fews times before my change appear

@Mugen87
Copy link
Collaborator

Mugen87 commented Apr 1, 2025

Would using the existing npm run build-module as an alternative be a solution? Or is this script considered to be too slow as well?

@gkjohnson
Copy link
Collaborator Author

Would using the existing npm run build-module as an alternative be a solution? Or is this script considered to be too slow as well?

Using the "configOnlyModule" flag works better but still takes around 7-9 refreshes before the content is available and the './three.core.js' does not provide an export named 'UniformsUtils' error is still present.

Changing the config so only builds[ 1 ] is built changes the process such that it only takes 4 refreshes to see the changes. Not as good as r150 but a significant improvement. Using only builds[ 1 ] also removes the ./three.core.js error which to me indicates that these builds are all being done separately and files are being built multiple times if specified multiple times.

Is there a reason all the modules files are separated as separate build entries for rollup?

@ycw ycw linked a pull request Apr 3, 2025 that will close this issue
@RenaudRohlinger
Copy link
Collaborator

I might be missing something here, and maybe other maintainers really do rely on the builds during development. But instead of always working with the built files, couldn’t we just update the Rollup config to alias all imports from build/three.webgpu.js to src/Three.WebGPU.js when in dev mode or something similar?
That way, we’d get real-time dev iteration and could even plug in HMR with minimal changes.

@donmccurdy
Copy link
Collaborator

Changing the config so only builds[ 1 ] is built changes the process such that it only takes 4 refreshes to see the changes.

builds[1] takes 1.5 seconds for me, and it sounds like our CPUs are similar — are we measuring the same thing? Note that only the last number of time output, not the first, is relevant to page refresh.

I'm not opposed to using source files in local development, just want to make sure there's not some more fundamental disconnect like having "Disable cache" off in devtools. 🙂

@gkjohnson
Copy link
Collaborator Author

gkjohnson commented Apr 4, 2025

couldn’t we just update the Rollup config to alias all imports from build/three.webgpu.js to src/Three.WebGPU.js when in dev mode or something similar?

I would be fine with this workflow personally. If there wind up being issues with code splitting it would (hopefully?) be caught in CI.

builds[1] takes 1.5 seconds for me, and it sounds like our CPUs are similar — are we measuring the same thing?

My machine measures 2.6s for builds[ 1 ] but either way I am attempting to measure the dev experience - there are number of factors at play, such as file overwriting as I mention above, that are extending the time. The numbers from a npm run build cold run are not really relevant.

If we want to look at raw numbers we should consider the values that rollup logs when it's watching files and rebuilding on change. In r150 it takes half a second to finish a build of the relevant file on change for me:

created build/three.module.js in 597ms

And in dev it takes over 1.5 seconds to finish even when running just builds[ 1 ]:

[2025-04-04 12:21:25] waiting for changes...
bundles src/Three.Core.js, src/Three.js, src/Three.WebGPU.js → build...
created build in 1.7s

just want to make sure there's not some more fundamental disconnect like having "Disable cache" off in devtools. 🙂

I am confident.

@ycw ycw linked a pull request Apr 4, 2025 that will close this issue
@ycw
Copy link
Contributor

ycw commented Apr 4, 2025

Time taken by builds creation varies from device to device and depends on modifications made, developers soon or later suffer the same degraded experience even if the measured numbers maybe decent right now. To me, tailoring bundles is not in right direction.

A reliable approach is that let developers retrieve the sources per se in browser, in turns refreshing page must reflect latest changes of them. Since it bypassed build creations, the time taken is now network-bound, not a big deal as server is serving on loopback, measured numbers would be similar between devices, and modifications made won't affect much; It does take longer on parsing scripts due to no minification, but it's negligible.

@gkjohnson
Copy link
Collaborator Author

Time taken by builds creation varies from device to device and depends on modifications made, developers soon or later suffer the same degraded experience even if the measured numbers maybe decent right now. To me, tailoring bundles is not in right direction.

To be clear I have no issue with a build step - it's possible for it to be fast on even extremely large projects. Other more modern build processes like vite cache and keep files split so only a limited number of files need to be transformed on change for development specifically. They also block reload until the bundle has finished if it does take time to avoid accidentally looking at "stale" changes and related mistakes.

That said I don't want to recommend overhauling and overcomplicating the build process for the repo. The simple changes suggested in #30865 seem good enough for me and address everything raised in this issue if everyone else is comfortable.

@ycw
Copy link
Contributor

ycw commented Apr 5, 2025

Thank you for the update, you want a deterministic environment that either renders the latest changes or render nothing if building is underway, and time-to-wait is not the most concern. In this case I prefer modern build process approach, it creates real build files so developers unlikely get into problems caused by unidentical builds (dev vs prod)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
7 participants