Import and Export Styles in Node.js
Let’s dive into the different styles of import and export in Node.js! Node.js supports two primary module systems: CommonJS (the traditional Node.js module system) and ES Modules (ESM) (the modern JavaScript standard). Each has its own syntax and quirks, so I’ll break them down clearly with examples.
1. CommonJS (CJS)
CommonJS is the original module system in Node.js, using require() for imports and module.exports or exports for exports. It’s synchronous and still widely used, especially in older projects.
Exporting in CommonJS
- Named Exports: You can export multiple items using the
exportsobject.javascript// math.js exports.add = (a, b) => a + b; exports.subtract = (a, b) => a - b; - Default Export: Use
module.exportsto export a single value or object.javascript// greet.js module.exports = (name) => `Hello, ${name}!`; - Mixing Both: You can combine named and default exports, but be cautious—
module.exportsoverridesexportsif redefined.javascript// mixed.js exports.foo = 'bar'; module.exports = { baz: 'qux' }; // Overrides exports.foo
Importing in CommonJS
- Named Imports: Access named exports via
require().javascriptconst { add, subtract } = require('./math'); console.log(add(2, 3)); // 5 - Default Import: Assign the entire export to a variable.javascript
const greet = require('./greet'); console.log(greet('Alice')); // "Hello, Alice!" - Dynamic Path: You can use variables with
require().javascriptconst moduleName = './math'; const { add } = require(moduleName);
Key Notes
- CommonJS is the default in Node.js unless
"type": "module"is set inpackage.json. - File extensions (e.g.,
.js) are optional inrequire()paths.
2. ES Modules (ESM)
ESM is the standardized JavaScript module system, introduced in Node.js v12+ and fully supported since v14. It uses import and export keywords and is asynchronous by nature.
Enabling ESM
- Add
"type": "module"inpackage.json. - Use the
.mjsfile extension (optional if"type": "module"is set). - Without these, Node.js defaults to CommonJS.
Exporting in ESM
- Named Exports: Export specific items with the
exportkeyword.javascript// math.mjs export const add = (a, b) => a + b; export const subtract = (a, b) => a - b; - Default Export: Export a single value with
export default.javascript// greet.mjs export default (name) => `Hello, ${name}!`; - Mixed Exports: You can combine named and default exports.javascript
// mixed.mjs export const foo = 'bar'; export default { baz: 'qux' };
Importing in ESM
- Named Imports: Use curly braces to import specific items.javascript
import { add, subtract } from './math.mjs'; console.log(add(2, 3)); // 5 - Default Import: Assign the default export to any variable name.javascript
import greet from './greet.mjs'; console.log(greet('Bob')); // "Hello, Bob!" - Import All (Namespace Import): Import everything as an object.javascript
import * as math from './math.mjs'; console.log(math.add(2, 3)); // 5 - Dynamic Import: Use
import()for asynchronous loading (returns a Promise).javascriptconst { add } = await import('./math.mjs'); console.log(add(2, 3)); // 5
Key Notes
- File extensions (e.g.,
.mjsor.js) are required in ESM paths unless using a module resolver. - ESM is static (analyzed at parse time), so
importstatements must be top-level and can’t use dynamic variables directly (useimport()instead).
3. Differences Between CommonJS and ESM
| Feature | CommonJS | ESM |
|---|---|---|
| Syntax | require(), module.exports | import, export |
| Loading | Synchronous | Asynchronous |
| File Extensions | Optional | Required (in Node.js) |
| Dynamic Import | require(variable) | import() (Promise) |
| Top-Level Await | Not supported | Supported (Node.js 14+) |
| Default in Node.js | Yes (unless overridden) | No (needs "type": "module") |
4. Interoperability
- CJS in ESM: You can import CommonJS modules in ESM using
import.javascriptimport myModule from './myCommonJsModule.js'; // Works if it uses module.exports - ESM in CJS: Use dynamic
import()sincerequire()can’t handle ESM natively.javascript(async () => { const { add } = await import('./math.mjs'); console.log(add(2, 3)); // 5 })();
5. Practical Tips
- Choosing a System: Use ESM for new projects (modern, standardized) and CommonJS for legacy compatibility.
- Mixing Systems: Be cautious—test thoroughly, as edge cases can trip you up.
- Node.js Version: ESM is stable in v14+, so ensure your runtime supports it if you go that route.