ESM runtime helper files should have the .mjs extension
See original GitHub issueBug Report
Current behavior
Config
{
presets: [
[
'@babel/env',
{
targets: {
node: '6.10',
browsers: '>1%'
},
modules: false,
shippedProposals: true,
loose: true
}
]
],
plugins: [
['@babel/transform-runtime', { useESModules: true }]
]
}
Input code
import React from 'react'
class Demo extends React.Component {}
Outputs:
import _inheritsLoose from '@babel/runtime/helpers/esm/inheritsLoose'
import React from 'react'
var Demo = (function(_React$Component) {
_inheritsLoose(Demo, _React$Component)
function Demo() {
return _React$Component.apply(this, arguments) || this
}
return Demo
})(React.Component)
When run as native ESM in Node.js with --experimental-modules
enabled:
node --experimental-modules lib/demo.mjs
@babel/runtime/helpers/esm/inheritsLoose
resolves to node_modules/@babel/runtime/helpers/esm/inheritsLoose.js
. Because Node.js can only run native ESM in files with the .mjs
extension, this results in a runtime error:
$ node --experimental-modules lib/demo.mjs
(node:97782) ExperimentalWarning: The ESM module loader is experimental.
/Users/jaydenseric/Sites/demo/node_modules/@babel/runtime/helpers/esm/inheritsLoose.js:1
(function (exports, require, module, __filename, __dirname) { export default function _inheritsLoose(subClass, superClass) {
^^^^^^
SyntaxError: Unexpected token export
at new Script (vm.js:74:7)
at createScript (vm.js:246:10)
at Proxy.runInThisContext (vm.js:298:10)
at Module._compile (internal/modules/cjs/loader.js:657:28)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
at Module.load (internal/modules/cjs/loader.js:599:32)
at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
at Function.Module._load (internal/modules/cjs/loader.js:530:3)
at createDynamicModule (internal/modules/esm/translators.js:56:15)
at setExecutor (internal/modules/esm/create_dynamic_module.js:50:23)
Expected behavior/code
The ESM helper import should resolve a helper file with a .mjs
extension.
Environment
- Babel version(s): v7.0.0-rc.1
- Node/npm version: Node.js v10.8.0 / npm v6.3.0
- OS: macOS v10.13.6
- Monorepo: No
- How you are using Babel: CLI
Possible Solution
Allow Babel helpers to be consumed in native CJS or ESM Node.js environments by publishing sibling .js
(CJS) and .mjs
(ESM) files. They should be imported using the same path so the Node.js import resolution algorithm will select the appropriate file for the environment:
- import _inheritsLoose from '@babel/runtime/helpers/esm/inheritsLoose'
+ import _inheritsLoose from '@babel/runtime/helpers/inheritsLoose'
Webpack and other tools have adopted the same resolution algorithm; Webpack actually prefers .mjs
files for ESM.
Additional context/Screenshots
I would like to be able to generate an ESM build, that imports ESM helpers, that can run as native ESM in Node.js with --experimental-modules
enabled.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:1
- Comments:10 (4 by maintainers)
Top GitHub Comments
To workaround this issue I’ve published
babel-plugin-transform-runtime-file-extensions
, a Babel plugin that adds file extensions to Babel runtimeimport
specifiers andrequire
paths for Node.js ESM compatibility.Fixed in
@babel/runtime@7.12.0
.