Skip to content

v0.16.6 - failed to start esbuild if any ESM loader was present #2747

@koshic

Description

@koshic

Install esbuild and run it with any ESM loader. In this example, I use 'bin' script directly to avoid package manager related things. Loader is empty (which is valid according to specs - just no resolve / load hooks will be added to the chain):

node --loader 'data:text/javascript,//' ./node_modules/esbuild/bin/esbuild

(node:1874) ExperimentalWarning: Custom ESM Loaders is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
node:internal/errors:484
    ErrorCaptureStackTrace(err);
    ^

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension "" for <some my machine path>/node_modules/esbuild/bin/esbuild
    at new NodeError (node:internal/errors:393:5)
    at Object.getFileProtocolModuleFormat [as file:] (node:internal/modules/esm/get_format:75:9)
    at defaultGetFormat (node:internal/modules/esm/get_format:114:38)
    at defaultLoad (node:internal/modules/esm/load:81:20)
    at nextLoad (node:internal/modules/esm/loader:161:28)
    at ESMLoader.load (node:internal/modules/esm/loader:594:26)
    at ESMLoader.moduleProvider (node:internal/modules/esm/loader:446:22)
    at new ModuleJob (node:internal/modules/esm/module_job:64:26)
    at #createModuleJob (node:internal/modules/esm/loader:469:17)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:423:34) {
  code: 'ERR_UNKNOWN_FILE_EXTENSION'
}

Node.js v19.2.0

From my understanding, the issue is related to the script extension (== no extension). It's OK for pure commonjs setup, but when we ask node to use loaders flow by --loader flag, node will execute defaultResolve / defaultLoad hooks for every incoming file. Next, defaultResolve can't handle files without extension, and return 'format: undefined' - which leads to fail inside defaultLoad.

'format: commonjs' at resolve stage (in my PoC I just test incoming url with '*/bin/esbuild' inside the hook) solves the issue - as per docs, it will activate some kind of CJS fallback. But it looks like a dirty hack )

So, proposed solution - to add .js (or even .cjs) extension to the 'bin' script (and change package.json too).

My use case (== 'why do you use loader here?') is simple - loader (simple ts transpiler) added for every 'yarn xxx' via NODE_OPTIONS yarn configuration, which is very useful for TS monorepo (no need to compile eslint / jest configs, etc.).

ps checked with node 18 too.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions