Babel core not importable with Node.js native ESM support
See original GitHub issueBug Report
- I would like to work on a fix!
Current Behavior
Babel version 7.8.7
import * as babelCore from '@babel/core' from an ESM in Node.js’s experimental support for ESMs produces an object with a transformSync accessor but the accessor returns undefined. This occurs when the containing package.json has "type": "module" set or when the file has the .mjs extension. The same module works fine when executed with node -r esm: babelCore.transformSync is a function. The same also works fine when required with CommonJS conventions.
Unexpected behavior for Node.js ESM support when file has .mjs extension:
// node test.mjs
import * as babelCore from "@babel/core";
console.log(babelCore.transformSync);
// (node:25847) ExperimentalWarning: The ESM module loader is experimental.
// undefined
Expected behavior: log a defined function object.
// [Function: spec]
Unexpected behavior for Node.js ESM support when file has a .js extension and module type in package.json:
// package.json
{
"type": "module"
}
// node test.js
import * as babelCore from "@babel/core";
console.log(babelCore.transformSync);
// (node:25847) ExperimentalWarning: The ESM module loader is experimental.
// undefined
As expected, the .mjs extension or module type in package.json are required to use native import.
// node test.js
import * as babelCore from "@babel/core";
console.log(babelCore.transformSync);
// (node:25839) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
// /Users/kris/ses/temp2.js:1
// import * as babelCore from "@babel/core";
// ^^^^^^
As expected, node -r esm does access a defined function.
// node -r esm test.js
import * as babelCore from "@babel/core";
console.log(babelCore.transformSync);
// [Function: sync]
As expected, node works fine when importing as CommonJS.
// node test.js
const babelCore = require("@babel/core");
console.log(babelCore.transformSync);
// [Function: sync]
It is possible that this behavior is due to aberrant behavior of Node.js’s ESM implementation. It is likely that this is a symptom of an underlying problem.
Issue Analytics
- State:
- Created 4 years ago
- Comments:9 (5 by maintainers)

Top Related StackOverflow Question
@kriskowal I wouldn’t phrase it as such since I don’t actually think this is a bug but an integration problem by the nature of the transpilation; note that babel file in question is CJS and CJS does not export named bindings in Node. I wouldn’t state that importing CJS is broken on Node’s side, nor would I state that babel creating CJS from ESM input is broken. They just don’t mix / no solutions have been able to be found. There are lots of issues exactly about this topic, from things on Node trackers, at TC39, and many more. In general mixing the transpiled ecosystem and spec ESM simply doesn’t work as it stands. So, once you cross the transpilation barrier things must adhere to their compilation target expectations (in the case of
@babel/corethat is CJS). I think babel could output ESM instead of CJS like rollup does, but even then more integration issues likely remain.I agree on what Bradley has said before:
@babel/coreis shipped in commonjs, if you are looking at the entry file, it is likeThe ESM named import
import { transformSync } from "@babel/core"is never expected to work with commonjsexports.transformSync.The
esmwill transform the commonjs exports to analogous esm exports sonode -r esmworks in your case.We are likely to ship dual cjs/esm builds of babel on Babel 9, which is expected in next year. So in the future it should be valid to do
At this moment the Node.js ES Module API is still experimental and Babel 8 is on the horizon, it is risky to ship esm builds for Babel 8. Before that please use
since
@babel/core, although written in ESM, is actually shipped in commonjs format.I am gonna close that because the current situation is expected.