Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
koshic opened this issue Dec 14, 2022 · 2 comments
Closed

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

koshic opened this issue Dec 14, 2022 · 2 comments

Comments

@koshic
Copy link

koshic commented Dec 14, 2022

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.

@evanw
Copy link
Owner

evanw commented Dec 14, 2022

It would be incorrect to add a JavaScript file extension to node_modules/esbuild/bin/esbuild because it's not JavaScript:

$ file node_modules/esbuild/bin/esbuild 
node_modules/esbuild/bin/esbuild: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, Go BuildID=iWVTDvMSaaeGwO_F8vaK/NFjtd-nUjLjQTPHhjwyu/z49zWfHmA6HcCqcPWWnL/unMqBi8H25Gzyhp9Paku, stripped

The underlying problem is that you're trying to run a binary executable through node. Don't do that. Just run it directly.

Edit: Sorry, I missed that you're using Yarn. My comment above was for people who install esbuild with a non-Yarn package manager. The install script overwrites the JavaScript file you're referencing with a binary executable for speed, but it doesn't do this for Yarn because Yarn has bugs regarding binary executables as bin scripts: yarnpkg/berry#882.

In any case, I'm not going to change the name of the esbuild command to esbuild.js. You are welcome to work around this problem in whatever way works best for you.

@koshic
Copy link
Author

koshic commented Dec 14, 2022

Thx, but why do you need to change 'esbuild' command? Just change filename and reference in package.json:
image

Especially if you are using 'full' form of 'bin' entry and specifying exact command name (== "esbuild") instead of "bin: ./bin/esbuild".

Or it means that you should change binary name for non-yarn envs, right?

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

No branches or pull requests

2 participants