Loading

Quipoin Menu

Learn • Practice • Grow

node-js / ES Modules in Node.js
tutorial

ES Modules in Node.js

While CommonJS has been the traditional module system in Node.js, JavaScript now has a standard module system called **ES Modules (ESM)**. It uses `import` and `export` keywords and is the official standard for JavaScript modules.

CommonJS vs ES Modules

AspectCommonJSES Modules
Syntax`require()` / `module.exports``import` / `export`
LoadingSynchronousAsynchronous
File Extension`.js` (default)`.mjs` or `"type": "module"` in package.json
Top-level `this``module.exports``undefined`
Dynamic imports`require()` anywhere`import()` function

Think of ES Modules as the modern, standardized way to organize code – like upgrading from VHS to Blu-ray.

Enabling ES Modules in Node.js

There are two ways to tell Node.js to use ES Modules:
  1. Use the `.mjs` file extension.
  2. Set `"type": "module"` in your `package.json` (then `.js` files are treated as ES modules).

package.json
{
  "name": "my-esm-project",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "start": "node index.js"
  }
}

Exporting with ES Modules

math.mjs
<!-- Named exports -->
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;

<!-- Default export -->
const multiply = (a, b) => a * b;
export default multiply;

<!-- Export all at once -->
const pi = 3.14159;
const e = 2.71828;
export { pi, e };

Importing with ES Modules
app.mjs
<!-- Import named exports -->
import { add, subtract, pi, e } from './math.mjs';

console.log(add(5, 3)); <!-- 8 -->
console.log(pi); <!-- 3.14159 -->

<!-- Import default export -->
import multiply from './math.mjs';
console.log(multiply(4, 3)); <!-- 12 -->

<!-- Import all as an object -->
import * as math from './math.mjs';
console.log(math.add(10, 5)); <!-- 15 -->

Dynamic Imports

ES Modules support dynamic imports using `import()` – which returns a promise. This is useful for code splitting or loading modules conditionally.
async function loadModule(moduleName) {
  try {
    const module = await import(`./${moduleName}.mjs`);
    console.log(module.add(2, 3));
  } catch (err) {
    console.error('Failed to load module', err);
  }
}

loadModule('math');

Important Differences

1. No `__dirname` or `__filename`
In ES Modules, `__dirname` and `__filename` are not available. Instead, use:
import { fileURLToPath } from 'url';
import { dirname } from 'path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

2. JSON Imports
In ES Modules, you need to use assertion syntax to import JSON:
import data from './data.json' assert { type: 'json' };

3. Top-level `await`
In ES Modules, you can use `await` at the top level without wrapping in an async function.
import fs from 'fs/promises';

const data = await fs.readFile('file.txt', 'utf8');
console.log(data);

Two Minute Drill

  • ES Modules are the official JavaScript module standard using `import`/`export`.
  • Enable them with `.mjs` extension or `"type": "module"` in package.json.
  • Supports named exports, default exports, and dynamic imports.
  • `__dirname` and `__filename` are not available – use `import.meta.url`.
  • Top-level `await` is allowed in ES Modules.

Need more clarification?

Drop us an email at career@quipoinfotech.com