ES Modules in Node.js: import, export and require(esm)

A
Author
30 Aug, 2026 1 min read 1.24K views

Node.js supports two module systems: the original CommonJS (require) and standard ES modules (import). New projects should use ESM, but you'll meet both.

Turning on ESM

// package.json
{ "type": "module" }

With "type": "module", .js files are ESM. Without it, they're CommonJS. .mjs is always ESM and .cjs is always CommonJS.

Syntax

// math.js
export function add(a, b) { return a + b; }
export default function multiply(a, b) { return a * b; }

// app.js
import multiply, { add } from './math.js';   // the extension is required
import fs from 'node:fs/promises';           // node: prefix for built-ins

No __dirname? Use import.meta

console.log(import.meta.dirname);   // directory of this file
console.log(import.meta.filename);  // full path of this file

const configPath = new URL('./config.json', import.meta.url);

Top-level await

const config = JSON.parse(await fs.readFile(configPath, 'utf8'));
await db.connect();

JSON imports

import pkg from './package.json' with { type: 'json' };

Mixing with CommonJS

  • ESM can import CommonJS packages; module.exports becomes the default export.
  • Current Node.js versions also let CommonJS require() an ES module, as long as it doesn't use top-level await. This removed the biggest pain of the migration.
  • In older versions, use dynamic await import() from CommonJS.

Common errors

  • Cannot use import statement outside a module - add "type": "module" or rename to .mjs.
  • ERR_MODULE_NOT_FOUND for a local file - add the .js extension to the import path.
  • require is not defined - you're in ESM; use import or createRequire.
Was this article helpful?

Comments

No comments yet. Have a question or a tip? Be the first to share it.

Leave a comment

Comments are reviewed before they appear.