How to import and export in CommonJS and ES Modules
CommonJS: modules are the original way to package JavaScript code for Node.js.
ES Modules: ES modules bring an official, standardized module system to JavaScript.
There are good articles out there to understand what they are and their differences. Here are the links that I read.
Before diving into code right away, I recommend you read these articles.
- commonjs-vs-es-modules
- CommonJS vs. ES Modules: Modules and Imports in NodeJS
- Modules in JavaScript – CommonJS and ESmodules Explained
CommonJS
Basic Usage
[aboutme.js]
const person = {
name: "Lico",
role: "Frontend Engineer",
};
function printName() {
console.log(person.name);
}
function printRole() {
console.log(person.role);
}
module.exports = {
person,
printName,
printRole,
};
[main.js]
const aboutme = require("./aboutme");
aboutme.printName();
aboutme.person.name = "lico!";
aboutme.printName();
You can change the variables that imported from other modules, but do not encourage to do.
Named Import
const { printName, printRole } = require("./aboutme");
printName();
printRole();
You can import it with Destructuring assignment.
Of course, if you do not export functions, you can't import the functions.
+ You can export anything instead of object
[aboutme.js]
const person = {
name: "Lico",
role: "Frontend Engineer",
};
function printName() {
console.log(person.name);
}
function printRole() {
console.log(person.role);
}
module.exports = {
// person,
// printName,
printRole,
};
[main.js]
const aboutme = require("./aboutme");
console.log(aboutme);
ES Modules
To use ES Modules
, I added this line into package.json
.
{
...
"type": "module"
...
}
Basic Usage
const person = {
name: "Lico",
role: "Frontend Engineer",
};
function printName() {
console.log(person.name);
}
function printRole() {
console.log(person.role);
}
export default {
person,
printName,
printRole,
};
import aboutme from "./aboutme.js";
aboutme.printName();
aboutme.person.name = "lico!";
aboutme.printName();
It's very similar to CommonJS
. You are also able to change the exported variables.
Named Import
import { printRole } from "./aboutme.js";
printRole();
It is going to occur an error like below.
SyntaxError: The requested module './aboutme.js' does not provide an export named 'printRole'
To use named import, you must export the functions.
export function printRole() {
console.log(person.role);
}
The error would be gone. you can export multiple functions and variables with only one export
keyword instead of put export
in front of every functions and variables that you want to export.
const person = {
name: "Lico",
role: "Frontend Engineer",
};
function printName() {
console.log(person.name);
}
function printRole() {
console.log(person.role);
}
export { person, printName, printRole };
export default {
person,
printName,
printRole,
};
And you are able to import with name.
import { printRole, printName } from "./aboutme.js";
printRole();
printName();
You also can use default
and Named Import
both together and you can use as
keyword to rename them.
import aboutme, { printRole as role } from "./aboutme.js";
console.log(aboutme);
aboutme.printName();
role();
Import with the Asterisk
[aboutme.js]
const person = {
name: "Lico",
role: "Frontend Engineer",
};
function printName() {
console.log(person.name);
}
function printRole() {
console.log(person.role);
}
export { person, printName, printRole };
export default {
person,
printName,
};
[main.js]
import * as aboutme from "./aboutme.js";
console.log(aboutme);
You see default
. That is the object which is exported using export default
.
Import a module which uses CommonJS
as a module system from ES Modules
[lib/aboutme.js]
const person = {
name: "Lico",
role: "Frontend Engineer",
};
function printName() {
console.log(person.name);
}
function printRole() {
console.log(person.role);
}
module.exports = {
person,
printName,
printRole,
};
[main.js]
import aboutme, { person, printName, printRole } from "./lib/aboutme.js";
console.log(person);
console.log(printName);
console.log(printRole);
console.log(aboutme);
You can use default
and Named Import
.
[main.js]
import * as aboutme from "./lib/aboutme.js";
console.log(aboutme);
As you see, there are default and exported functions and a variable.
You cannot import a module which uses ES Modules
as a module system from CommonJS
. If you try it, you will see like this error. (With a bundler, it will be working)
I hope you found it useful.
Enjoy your coding!
Top comments (3)
Importing ES modules into CommonJS can be tricky, but I figured out a way to do it. For example, Node 18 introduced top-level
fetch
. I wanted to implement a polyfill for Node 16 to fall back to using the ES modulenode-fetch
.I wanted to do
import * as fetch from 'node-fetch'
, but CommonJS does not support it. So instead I implemented it like this:The lets me invoke
fetch
in a CommonJS module in both Node 16 and Node 18:fetch('https://foo.com/do_something').then(...)
. Node 18 uses the native top-levelfetch
, while Node 16 falls back to the ES modulenode-fetch
.The idiom works for any ES module that exports an object that returns a then-able function.
Very helpful! Could you show me the content of package.json file in your last example project ?
I couldn't find the project, so, I've reproduced it.
They should be like the followings.
[package.json]
[lib/package.json]