three.js: Stringified DracoLoader body fails to load with vite ``build.keepNames: true``
Describe the bug
When using vite.js configured with keepNames: true
and glTF transform with draco compression and referencing a local draco_decoder.js
at runtime we receive a Uncaught ReferenceError: m is not defined
error.
Probably caused by this section in DRACOLoader
To Reproduce
Steps to reproduce are described here with a minimal repo that produces the error here.
Code Please see this repository here
Live example live example
Expected behavior Mesh gets decompressed
Screenshots
Platform:
- Device: any
- OS: Win10
- Browser: Chrome
- Three.js version: r144
About this issue
- Original URL
- State: open
- Created 2 years ago
- Comments: 15 (1 by maintainers)
Yes, exploring some options in https://github.com/mrdoob/three.js/pull/24946 — it updates KTX2Loader but the same options would apply to DRACOLoader.
When I remember correctly, @mrdoob suggested to remove
examples/js
at the end of this year (r148
).Definition of
m
, injected by esbuild —In short, esbuild is injecting code into the bundle that defines a function
m
, which implements thekeepNames
behavior. And then esbuild injects references to that function elsewhere in the bundle. Because DRACOLoader needs to serialize and transfer the decoder implementation to a Web Worker, we intentionally avoid any reference to the function’s scope (which cannot be transferred), but esbuild is injecting scope-dependent functions here.Unfortunately, this is not so easy to work around. I suppose if all of the transferable code were stored as a string in
DRACOLoader.js
, esbuild wouldn’t be able to process it, and we wouldn’t have a problem. Quite an ugly solution but it may be our only one right now.The Web Worker API is unfortunately designed with web applications in mind, and really doesn’t lend itself easily to libraries like three.js, which need to support downstream consumers with unknown build processes. This has been a recurring problem for us over the years.
Newer build tools do make Web Workers more practical, and (in theory) should fix these issues using code that also works without a bundler:
However, I don’t know how to make that switch while keeping our
examples/js
builds working. I hope theexamples/js
builds will go away within a year or so, in favor of ES Modules inexamples/jsm
. If there’s a workaround possible that would save us from making deeper changes here until that happens, it would be my preference … I am curious if things work correctly withoutkeepNames
, or if that introduces other problems?/cc @gkjohnson