tezvyn:

Choosing between CommonJS and ES Modules

AI-drafted, machine-checkedSource: interviewintermediate
WHAT IT TESTS

knowing the two module systems and their config.

OUTLINE

ESM is the standard with static import/export and top-level await; set type to module; CJS uses require and module.exports and is synchronous.

WHAT THIS TESTS This evaluates whether you can make an informed module-system choice and configure it correctly, including the gotchas that bite teams migrating between the two.

A GOOD ANSWER COVERS ES Modules are the JavaScript standard. They use static import and export statements, are analyzed before execution which enables tree-shaking and circular handling via live bindings, and support top-level await. You opt in by setting type to module in package.json or naming files .mjs. CommonJS is the historical Node default, uses require and module.exports, loads modules synchronously at call time, and is selected by type commonjs or the .cjs extension. For a new project, ESM is usually the right default unless a critical dependency or tooling only ships CommonJS. Key differences: ESM does not provide __dirname or __filename, so you derive them from import.meta.url; require is not available by default in ESM; and importing a CommonJS module from ESM works, but requiring an ESM module from CommonJS does not without dynamic import.

COMMON WRONG ANSWERS Claiming you can freely mix require and import in the same file, saying import is merely syntactic sugar over require, or ignoring the loss of __dirname and the synchronous-versus-static loading distinction.

LIKELY FOLLOW-UPS How dynamic import bridges the two, what the exports field in package.json controls, how live bindings differ from the value-copy semantics of CommonJS, and bundler implications.

ONE CONCRETE EXAMPLE In an ESM project you write import express from 'express' and add type module to package.json. To get the current directory you compute it with fileURLToPath and import.meta.url, because __dirname is undefined. In a CommonJS project the equivalent is const express = require('express'), and __dirname is available directly. Trying to require an ESM-only package from CommonJS throws, forcing you to use an asynchronous dynamic import instead.

Read the original → nodejs.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.