Short answer
At the moment you cannot run CoffeeScript source files directly with
node --experimental-modules and have them behave as native ES modules.
The CoffeeScript command-line tool works by installing a “require hook”
that on-the-fly compiles the .coffee file and then lets Node execute
the resulting JavaScript as a CommonJS module.
The ES-module loader that Node exposes under
--experimental-modules:
require hooks completely, andBecause of that the sequence
npx coffee --nodejs --experimental-modules a.coffee
fails in the way you observed:
• Node sees a CommonJS module (CoffeeScript’s hook told it to execute
the generated code in CommonJS mode);
• the generated code still contains the import keyword, which is
illegal inside CommonJS;
• a SyntaxError is thrown.
Why the usual tricks do not help
• Changing the filename extension to .mjs is impossible – the file is
still called a.coffee when the loader makes its decision.
• Putting "type":"module" in package.json does not help for the same
reason: the source file being executed is not JavaScript.
What does work
Compile first, run later
Compile your CoffeeScript ahead of time, save the result with an
extension that Node recognises as an ES module, then start Node
without involving the CoffeeScript CLI:
# Compile
npx coffee -c a.coffee b.coffee # produces a.js and b.js
mv a.js a.mjs
mv b.js b.mjs
# OR leave them as .js but put "type": "module" in package.json
# Run
node --experimental-modules a.mjs
In that setup Node never sees any .coffee files; it only sees plain
JavaScript and can treat it as ESM.
Write a custom loader (advanced / experimental)
Since Node 12 you can provide your own loader with
--experimental-loader. A loader could read a .coffee file,
compile it to JavaScript, and hand that source back to Node. This is
not something the CoffeeScript project ships today and is still
considered experimental in Node.
Stay with CommonJS for the time being
If you want to continue running CoffeeScript source directly with
npx coffee …, use require/module.exports; CommonJS is still fully
supported by current and future Node versions.
So, with current releases the choices are:
• pre-compile and run the generated JavaScript as ES modules, or
• keep using CommonJS when executing CoffeeScript on the fly.
There is no supported way to mix “CoffeeScript executed on the fly” and Node’s native ECMAScript-module loader today.
Was this answer helpful?
version: o3-pro-2025-06-10
Status: UQ Validated
Validated: 8 months ago
Status: Needs Human Verification
Loading model reviews...
Loading reviews...