I want to make my ES module importable in both following styles:
import * as mylib from "./mylib.mjs";
import mylib from "./mylib.mjs";
Then I wrote mylib.mjs
in following style:
export function foo(){
}
export function bar(){
}
export function baz(){
}
// ... and many export functions...(1)
export default {foo, bar, baz, /* ... and many function names...(2) */};
But I always have to worry about some names missing in export default(2)
. If a new export functions(1)
is added, I have to add it also in function names(2)
. I often forget this.
In CommonJS, using exports
makes this smarter. Is there any variable that is equivalent to exports
in ES module?
exports.foo=function () {
};
exports.bar=function () {
};
exports.baz=function () {
};
exports.default=exports;// No need to change here when function export is added.
This is not something I would advise doing as I feel barrel files are an anti-pattern, and it is better to have one way for loading your modules, but something you could do to get close to what you want is to organize your project like this:
.
└── src/
├── mylib/
│ └── mod.mjs
├── mylib.mjs
└── consumer.mjs
mylib/mod.mjs
export function foo(){
}
export function bar(){
}
export function baz(){
}
mylib.mjs
export * from './mylib/mod.mjs'
export * as default from './mylib/mod.mjs'
consumer.mjs
import * as mylibNs from './mylib.mjs'
import mylib from './mylib.mjs'
Requires an extra file to manage the the exports, but you won't have to update the exported names in multiple places.
Of course if you're ok with circular references in your modules, you can have just one file like this:
mylib.mjs
export function foo() {
}
export function bar() {
}
export function baz() {
}
export * as default from './mylib.mjs'
It would be consumed the same way as before, but the default
property would be a reference back to the module itself, i.e. mylib.default === mylib
.
This was tested using Node.js v20.12.0.