Repo to document all my findings about authoring, publishing and working with commonjs and esm in Node
I am not sure yet if it is realistic, I'm not even sure if this all makes sense, but I want to find a way to build and publish a JavaScript package that works both in the Browser and in Node with the minimal possible effort. With commonjs and esm. With support for treeshaking. Without going crazy on configuration or build steps and without changing the way you're working right now (or at least without changing it too much).
The main reason for this investigation is a (still unresolved) issue I got in an open source project of mine. At the time of writing this, I have absolutely no idea how an ideal solution to that issue could look like.
<script src></script>
<script type="module" src></script>
require()
in Nodeimport x from 'x'
, without additional build step required).cjs
file endings without explicitly sending a application/javascript header (assumption: they do).cjs
files without explicit configuration (assumption: as long as the main
property in package.json points to a .cjs
file, they do)import
particular ESModules without complaining12.11.0
→ 12.11.1
, 12.12.0
, 12.13.0
→ 12.13.1
when type
is set to module
in package.json..mjs
or if it is inside of a project that has "type":"module"
defined in its package.json. In this case .js
also works.import add from './add.js'
works while import add from './add'
does not). This is according to the current spec and matches Browser behavior as far as I can tell."type":"module"
in your package.json, you can use .cjs
for commonjs modules../example/es/index.js
with ESLint with eslint-plugin-unicorn
and autofix enabled, the unicorn/import-index
rule automatically shortens the path to ./example/es
making the script fail."type":"module"
is set in package.json, files need to be named .mjs
to tell Node it's an ESModule. Babel, however, does not yet support writing file extentions other than .js
. There's been an open PR to add a new --out-file-extension
option to babel-cli
but it hasn't been merged yet. Update: will probably be released with Babel 7.8!
"type":"modules"
for the complete package due to the lack of support for .mjs
as output file extension..mjs
file-extension. Until this is done, there's also no safe support for .mjs
as indicator for ES Modules..cjs
files as JavaScript but use plaintext
instead. This can be configured by setting:
"files.associations": {
"*.cjs": "javascript"
}
.mjs
however, is correctly detected as JavaScript."type":"module"
is set, you can't use .babelrc.js
or webpack.config.js
anymore but you must stricly use .cjs
and rename them .babelrc.cjs
and webpack.config.cjs
. That is because @babel/core
is still using require()
to load config files. However, Babel looks for the existence of a .babelrc.cjs
file automatically (source). Webpack does not. You have to add --config webppack.config.cjs
explicitly.exports
property in package.json
for Node. It is a map containing aliases to tell Node where to look for imports. See Node docs on ECMAScript Modules for more info.If you wanna try it out yourself:
yarn
npx lerna bootstrap --force-local
More docs on that coming soon
tbd.