Node soporta dos sistemas de módulos: CommonJS (CJS) — el original, que usa require/module.exports — y ES Modules (ESM) — el estándar, que usa import/. Difieren en sintaxis, comportamiento de carga e interoperabilidad.
Node soporta dos sistemas de módulos: CommonJS (CJS) — el original, que usa require/module.exports — y ES Modules (ESM) — el estándar, que usa import/. Difieren en sintaxis, comportamiento de carga e interoperabilidad.
export// math.js
function add(a, b) { return a + b; }
module.exports = { add };
// app.js
const { add } = require("./math"); // síncrono, en runtime
// math.mjs (o .js con "type": "module")
export function add(a, b) { return a + b; }
export default something;
// app.mjs
import { add } from "./math.mjs"; // estático, hoisted
CommonJS ES Modules
Sintaxis require/module.exports import/export
Carga síncrona, en runtime estática, hoisted
Top-level await no sí
Tree-shaking difícil sí (analizable estáticamente)
Extensión .cjs / .js (por defecto) .mjs / .js con "type":"module"
__dirname/__filename disponibles no disponibles (usa import.meta.url)
// package.json
{ "type": "module" } // ahora los archivos .js se tratan como ESM
O usa la extensión .mjs explícitamente. Sin esto, Node trata por defecto .js como CommonJS.
// ESM puede importar CommonJS:
import pkg from "some-cjs-lib"; // funciona (default import)
// CommonJS NO PUEDE hacer require() de un paquete puramente ESM (es asíncrono):
const esm = require("esm-only-pkg"); // ❌ ERR_REQUIRE_ESM
// debe usar dynamic import: const esm = await import("esm-only-pkg");
El punto delicado: CJS no puede hacer require() de paquetes solo-ESM — un dolor de cabeza común en las migraciones. Nota también que ESM carece de __dirname (usa import.meta.url).
Conocer ambos sistemas es esencial para el trabajo real con Node: ESM es el futuro (estándar, tree-shakeable, top-level await, alineado con el navegador) y la opción correcta para proyectos nuevos, pero una enorme cantidad del ecosistema npm y del código existente es CommonJS.
Entender las diferencias de sintaxis, cómo habilitar ESM ("type": "module") y las limitaciones de interoperabilidad (especialmente que CJS-no-puede-hacer-require-de-ESM) previene la confusión y los errores frecuentes que surgen al mezclarlos.