draco
draco copied to clipboard
Modernizing Draco package - ES modules and unifying NodeJS/Browser builds.
Hi,
I'm a user of the draco3d library for glTF encoding/decoding - I am also a contributor to the glTF standards. It is quite challenging to use this library in its current form. A few combined issues make it quite challenging:
- The npm packages only supports node.js operation and has hard coded dependences on NodeJS-specific fs and path libraries as well as relying on __dirname, which isn't available in ES modules.
- The npm packages rely upon CommonJS rather than more modern ES modules, thus you need to use old school bundlers.
- The browser version of the library isn't in any npm package, thus you have to copy it manually into projects.
- The browser version of the library also doesn't have typings (e.g. @types/draco is only for the node.js-specific npm module.)
Together this makes this library super old-school and a pain to use, even though it has awesome functionality.
The best way forward would be to:
- update the npm package so that the decoder/encoder is not dependent upon either the browser or Node.JS, rather it is independent and just operates on ArrayBuffers.
- the npm package should be published in at minimum ES module format, and I guess you can keep the CommonJS. Use the "module" and "main" fields of the "package.json" respectively for this dual publishing method.
- There is a function on the main wrapper in which you can pass in the WASM file. So you can load it differently depending on the platform, but once loaded you initialize it into the library the same way.
Relying upon primarily the emscripten version would allow one to just package this up so that anyone can use it. Trying to load the WASM module makes things a lot more complex because import support for WASM nor bundler support for WASM is here yet.
This would allow something like this in Node.js:
import { createDecodeModule } from 'draco3d';
import { fs } from 'node:fs'
const wasmBuffer = fs.readFileSync('/path/to/add.wasm');
createDecodeModule( wasm: wasmBuffer );
And this code in the browser:
import { createDecodeModule } from 'draco3d';
const wasmBuffer = await fetch( '/path/to/add.wasm');
createDecodeModule( wasm: wasmBuffer );
And both scenarios would share the same typing and the same ES module.
I know the is a big ask so it probably won't happen, but I figured I'd share a way forward that seems reasonable. Thanks for your attention.