DEV Community

Tanmay Gupta
Tanmay Gupta

Posted on

Using ECMAScript Modules (ESM) Instead of CommonJS in Node.js

By default, most Node.js projects use CommonJS syntax (require, module.exports). But modern JavaScript has standardized ES Modules (ESM), which use import and export statements, just like in frontend development.

In this post, you’ll learn:

  • The difference between CommonJS and ESM
  • How to set up ESM in a Node.js + Express app
  • How to write modern import/export syntax

Why Use ESM?

ESM is the official module system in modern JavaScript. Benefits include:

  • Cleaner, standard syntax (import / export)
  • Top-level await support (await without async function wrapper)
  • Shared syntax with frontend JavaScript (React, Vue, etc.)
  • Future-proofing for new features

Step 1: Tell Node.js to Use Modules

In your package.json, add:

{
  "type": "module"
}
Enter fullscreen mode Exit fullscreen mode

This tells Node.js to treat .js files as ES modules.


Step 2: Convert require to import

Here’s a CommonJS example:

const express = require('express');
const mongoose = require('mongoose');
const connectDB = require('./config/db');
Enter fullscreen mode Exit fullscreen mode

Converted to ESM:

import express from 'express';
import mongoose from 'mongoose';
import connectDB from './config/db.js'; // .js extension is required
Enter fullscreen mode Exit fullscreen mode

⚠️ Important: You must include file extensions like .js in relative imports with ESM.


Step 3: Convert module.exports to export default

In CommonJS:

module.exports = connectDB;
Enter fullscreen mode Exit fullscreen mode

In ESM:

export default connectDB;
Enter fullscreen mode Exit fullscreen mode

You can also export multiple named items:

export const greet = () => console.log('Hi');
export const sayBye = () => console.log('Bye');
Enter fullscreen mode Exit fullscreen mode

And import them like this:

import connectDB from '../config/db.js'; // default import can be named anything
import { greet, sayBye } from './utils.js';
Enter fullscreen mode Exit fullscreen mode

Step 4: Update All Files

Here’s an example of a basic Express server with ESM:

// server.js
import express from 'express';
import dotenv from 'dotenv';
import connectDB from './config/db.js';
import postRoutes from './routes/postRoutes.js';

dotenv.config();
connectDB();

const app = express();
app.use(express.json());

app.use('/api/posts', postRoutes);

const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}`);
});
Enter fullscreen mode Exit fullscreen mode

When Should You Use ESM?

Use ESM if:

  • You want modern syntax and top-level await
  • You work with frontend frameworks that use ESM
  • You’re starting a new project or using newer libraries that support it

Use CommonJS if:

  • You’re working on an older Node.js codebase
  • You rely on older packages that don’t support ESM yet

Summary

Feature CommonJS ESM (Modules)
Import require() import from
Export module.exports export / export default
File extensions Optional Required (.js, .json)

Using ESM makes your codebase cleaner, consistent with modern JavaScript, and ready for future features.

Top comments (0)