Unable to bundle WASM modules read by `node:fs`
craxal opened this issue · 4 comments
The ESBuild documentation provides a sample plugin that can bundle WASM modules. The primary issue with this plugin and the theory behind it is it assumes code is importing WASM modules like any other module (that is, using import
or require()
). To my knowledge, this isn't standard (or at least, not yet), and this doesn't work for code trying to pull in WASM modules directly, such as from the file system.
//index.js
import { add } from "wapper";
console.log("Sum: ", add(6, 2));
// wapper.js
import { join } from "path";
const path = join(__dirname, "some.wasm");
const buffer = readFileSync(path);
const wasmModule = new WebAssembly.Module(buffer);
const wasmInstance = new WebAssembly.Instance(wasmModule);
export const { add } = wasmInstance.exports;
Under trivial situations, it may be possible to simply include the WASM file alongside the bundle, and the code will just "work". It's unclear whether this would work for more complex scenarios.
There is a native support to import wasm in Node.js but behind a flag: --experimental-wasm-modules.
Another possible way to do that is import source
which is still in stage 2. So it is not implemented in esbuild.
Both 2 methods above should be analysable by bundlers.
The "standard" way to use wasm or any external files is not analysable as it is not a simple import/require
. It is the same reason about URL assets bundling not landed yet. Because it is just too complex to track the usage of node:path
or to track the URL being used to load files.
@hyrious Thanks for the quick reply. Yeah, I figured this was more or less a problem that could extend beyond the scope of ESBuild. By no means would I expect ESBuild to statically analyze usage of node:path
or node:fs
. The annoying part about this is the means by which the WASM is "imported" is in a 3rd-party component, and therefore out of our control.
This is intentional. Emulating node's file system APIs is out of esbuild's scope. You can use --external:wapper
or --packages=external
to exclude either this package or all packages from the bundle, then ensure that the package is on the file system at run time. This is covered in the getting started instructions: https://esbuild.github.io/getting-started/#bundling-for-node
Note that import source
for Wasm is stage 3 (https://github.com/tc39/proposal-source-phase-imports) and being implemented currently, so may be suitable for build tools already.