Skip to content

fix(core): externalize wasm-pack packages in the config bundler - #28

Merged
garrettmflynn merged 2 commits into
devfrom
fix/config-bundler-wasm-external
Oct 11, 2026
Merged

garrettmflynn merged 2 commits into
devfrom
fix/config-bundler-wasm-external

Conversation

@garrettmflynn

Copy link
Copy Markdown
Member

Config files that import a wasm-pack --target nodejs package fail to load from the ESM build with ReferenceError: __dirname is not defined in ES module scope. The config is bundled into a single ES module, and wasm-pack's Node output is CommonJS that locates its .wasm through __dirname.

Fix: the config bundler now keeps *-wasm and wasm-* packages external, so Node loads them from node_modules as CommonJS at runtime.

Test: tests/esm-dist.test.ts builds a project whose config imports a CommonJS package that reads a file next to itself through __dirname, then loads it with loadConfigFromFile from dist/main.mjs in a separate Node process. It passes with the fix and fails with the __dirname error when the externals are removed.

esbuild bundles the user's commoners.config.ts into a `.mjs` ESM
snapshot. If that config statically imports a wasm-pack `--target
nodejs` output (CJS using `__dirname` + `require('fs')`), esbuild
wraps the CJS module but the `__dirname` reference has no value in
ESM scope → "__dirname is not defined in ES module scope" with no
stack at launch.

Wasm-pack Node outputs are not structurally bundlable into ESM
without rewriting their sync-load path. The cleanest fix is to mark
them external so Node's real resolver loads them at runtime, where
their nested package.json (`"type": "commonjs"` if the consumer set
it) is honored.

Widens the config-bundle externals from a hardcoded list to also
match `*-wasm` and `wasm-*` globs. esbuild's `external` field
supports prefix/suffix wildcards but not regex — `*-wasm` matches
wasm-pack packages; `wasm-*` mirrors for the other
naming convention.

Caller pattern (verified in a downstream app):
  package.json:
    "type": "module",
    "exports": {
      ".": {
        "node": "./node/pkg.js",
        "browser": "./web/pkg.js",
        "default": "./web/pkg.js"
      }
    }
  node/package.json:
    { "type": "commonjs" }

(cherry picked from commit 44fbea4)
…SM build

Config files are bundled into one ES module before Node loads them.
wasm-pack's --target nodejs output is CommonJS that finds its .wasm through
__dirname, so bundling it in fails with "__dirname is not defined in ES
module scope". The bundler already keeps *-wasm and wasm-* packages
external; nothing tested it.

The new test builds a project whose config imports a CommonJS package
that reads a file next to itself through __dirname, then loads it with
loadConfigFromFile from dist/main.mjs in a separate Node process. With
the *-wasm external removed, it fails with the __dirname error.

tests/esm-dist.test.ts is new on this branch; it holds only this test.
The child script catches and prints the load error, since an unhandled
rejection there can exit 0 with no output.

(cherry picked from commit f9fcbb0)
@garrettmflynn
garrettmflynn merged commit c7d54d2 into dev Oct 11, 2026
12 of 21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant