CommonJS and ES Modules
Combining CommonJS and ES Modules in Node.js
In its early versions, Node.js only used the CommonJS module system (require
and module.exports
). However, over time Node.js began supporting ES Modules (import
and export
) as well, giving developers more flexibility.
Today it's possible to use both systems, but there are some important nuances when combining them.
For Node.js to recognize your file as an ES Module, you need to do one of the following:
index.mjs
)"type": "module"
field in your package.json file:
{
"type": "module"
}
Then all .js
files will be treated as ES Modules.
If you have a CommonJS module and want to use it from ES Modules, you need to use a special import format. For example:
// greet.cjs file (CommonJS)
module.exports = function(name) {
return `Hello, ${name}!`;
};
// main.mjs file (ES Module)
import greet from './greet.cjs';
console.log(greet('Ani')); // Hello, Ani!
Node.js will automatically convert the CommonJS module to behave like a default export so it can be imported.
If you want to use an ES Module in CommonJS code, it's a bit more complicated. You can't directly require()
an ES Module. In this case, you need to use the dynamic import()
function which returns a Promise.
// greet.mjs file (ES Module)
export function greet(name) {
return `Hello, ${name}!`;
}
// main.cjs file (CommonJS)
async function loadGreet() {
const { greet } = await import('./greet.mjs');
console.log(greet('Ani')); // Hello, Ani!
}
loadGreet();
This approach requires async functions since the import() function returns a Promise.
Node.js now supports both CommonJS and ES Modules, but when combining them it's important to understand the syntactic and technical differences. For new projects, it's recommended to prefer ES Modules when possible, as they align with modern JavaScript standards and provide better compatibility with advanced tools.