Nodejs Commonjs Esm
When you start writing a Node.js project, one of the first issues you encounter is how to import modules.
In Node.js, a module is a reusable JavaScript file that communicates with other modules through imports and exports.
The Node.js ecosystem primarily supports two module systems: **CommonJS** and **ES Modules (ESM)**.
| Module System | Specification | File Extension | Import Method | Export Method |
| --- | --- | --- | --- | --- |
| **CommonJS** | Early Node.js usage | `.js` | `require()` | `module.exports` / `exports` |
| **ES Module (ESM)** | ECMAScript standard | `.mjs` or `"type": "module"` | `import` | `export` / `export default` |
* * *
## CommonJS Module System
CommonJS is the earliest and most widely used module system in Node.js. It employs synchronous loading, meaning that when a module is loaded, it blocks the execution of the program until the loading is complete.
### Importing and Exporting
In CommonJS, you use the `require()` function to import modules and the `module.exports` or `exports` object to export them.
**Exporting Methods:**
## math.js File Code:
// math.js
function add(a, b){
return a + b;
}
module.exports={ add };
// Or: exports.add = add;
**Importing Methods:**
## Example
// app.js
const math = require('./math.js');
console.log(math.add(2,3));// 5
For a module to be accessible externally, you need to use `module.exports` or `exports` to export its contents:
## Example
// user.js
const name ='Alice';
const age =30;
// Method 1: Use `module.exports` to export a single object or value
module.exports={
name: name,
age: age,
sayHello:()=>{
console.log(`Hello, my name is ${name}.`);
}
};
// Method 2: Use `exports` to export multiple named variables
// `exports` is a reference to `module.exports`
exports.name= name;
exports.age= age;
exports.sayHello==>{
console.log(`Hello, my name is ${name}.`);
};
**Importing Methods:**
## Example
// main.js
const user = require('./user.js');
console.log(user.name);// Output: Alice
user.sayHello();// Output: Hello, my name is Alice.
// You can also directly destructure
const{ name, age }= require('./user.js');
console.log(name);// Output: Alice
**CommonJS Features:**
* **Synchronous Loading**: Suitable for server-side environments because modules are typically stored on the local file system, making loading fast.
* **Runtime Loading**: The `require()` function can be called anywhere in your code, allowing you to dynamically load modules based on conditions.
* **Caching Mechanism**: Modules loaded by `require()` are cached, so subsequent imports retrieve them directly from the cache, avoiding redundant loading.
* * *
## ES Module (ESM) Specification
ESM is the official JavaScript module standard. It uses asynchronous loading and is the preferred choice for browsers and modern Node.js applications.
In ESM, you use the `import` statement to import modules and the `export` statement to export them.
**Enabling ESM:** To use ESM in Node.js, you need to add `"type": "module"` to your `package.json` file or change the file extension to `.mjs`.
// package.json{ "type": "module"}
**Exporting Modules:**
## Example
// math.mjs
export function add(a, b){
return a + b;
}
export default function multiply(a, b){
return a * b;
}
**Importing Modules:**
## Example
// app.mjs
import multiply,{ add } from './math.mjs';
console.log(add(2,3));// 5
console.log(multiply(2,3));// 6
**Enabling Methods:**
* Use the `.mjs` file extension
* Or add the following to `package.json`:
{ "type": "module"}
ESM supports two types of exports: Named Exports and Default Exports.
## Example
// user.mjs
// Named Exports
export const name ='Bob';
export const age =25;
// Default Export
const sayHello =()=>{
console.log(`Hello, my name is ${name}.`);
};
export default sayHello;
**Importing Methods:**
## Example
// main.mjs
// Importing Named Exports
import{ name, age } from './user.mjs';
console.log(name);// Output: Bob
// Importing Default Exports
import sayHello from './user.mjs';
sayHello();// Output: Hello, my name is Bob.
// Importing Both Named and Default Exports Simultaneously
import sayHello,{ name } from './user.mjs';
console.log(name);
sayHello();
// Importing All Named Exports as Properties of an Object
import* as user from './user.mjs';
console.log(user.name);
user.default();// Default exports appear as the `default` property
**ESM Features:**
* **Asynchronous Loading**: By default, ESM loads asynchronously without blocking the main thread, making it more suitable for browser environments, though in Node.js it often behaves synchronously.
* **Static Analysis**: The `import` and `export` statements allow dependencies to be determined before code execution, enabling tools like Webpack and Vite to perform better optimizations such as **Tree Shaking**.
* **Strict Mode**: ESM modules run in strict mode by default.
* * *
## Differences Between CommonJS and ESM
| Feature | CommonJS | ESM |
| --- | --- | --- |
| Syntax | `require` / `module.exports` | `import` / `export` |
| Loading Mechanism | Runtime synchronous loading | Compile-time static loading |
| Default Support | Node.js supports it by default | Requires `.mjs` or `"type": "module"` |
| Suitable Scenarios | Backend scripts, legacy projects | Modern full-stack projects, Tree-shaking |
| Can They Be Mixed? | Cannot be mixed directly (requires additional configuration) | Cannot be mixed directly (requires additional configuration) |
### Mixed Usage
Node.js supports coexistence of both module systems in newer versions. You can use CommonJS and ESM simultaneously within the same project, but keep the following points in mind:
* **ESM cannot directly use `require()` and `module.exports`.**
* **CommonJS cannot directly use `import` and `export`.**
* If you want to import a CommonJS module into an ESM environment, simply use the `import` statement; ESM will treat it as a default export.
// commonjs_module.jsmodule.exports = { data: 'hello' };// esm_module.mjsimport commonModule from './commonjs_module.js'; console.log(commonModule.data); // Output: hello
* If you want to import an ESM module into a CommonJS environment, you must use the dynamic `import()` function.
// esm_module.mjsexport const name = 'Bob';// commonjs_module.js async function loadESM() { const { name } = await import('./esm_module.mjs'); console.log(name);} loadESM();
### Best Practice Recommendations
For new projects, **we strongly recommend using ES Modules (ESM)**. Not only is it the official JavaScript standard, but it also offers better compatibility with modern frontend toolchains like Vite and Next.js, allowing you to fully leverage optimization techniques such as Tree Shaking to reduce the size of your bundled code.
If you're maintaining an older CommonJS project and don't require ESM features, you can continue using CommonJS. However, if you need to introduce new dependencies or take advantage of ESM's advanced features, consider gradually migrating or adopting a hybrid approach to transition smoothly.
YouTip