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 image

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)

Most upvoted comments

Yes, exploring some options in https://github.com/mrdoob/three.js/pull/24946 — it updates KTX2Loader but the same options would apply to DRACOLoader.

I hope the examples/js builds will go away within a year or so,

When I remember correctly, @mrdoob suggested to remove examples/js at the end of this year (r148).

Definition of m, injected by esbuild —

var er = Object.defineProperty;
var m = (d,t)=>er(d, "name", {
    value: t,
    configurable: !0
});

In short, esbuild is injecting code into the bundle that defines a function m, which implements the keepNames 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 the examples/js builds will go away within a year or so, in favor of ES Modules in examples/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 without keepNames, or if that introduces other problems?

/cc @gkjohnson