¿Cuál es la diferencia entre CommonJS y ES Modules en Node.js, y cómo activas cada uno?
Ver respuesta — intenta responderla en voz alta primero
CommonJS (CJS) es el sistema de módulos histórico de Node: usa require() y module.exports, y carga los módulos de forma síncrona. ES Modules (ESM) es el estándar oficial de JavaScript: usa import y export, y su carga es asíncrona. Activas ESM usando la extensión .mjs o poniendo "type": "module" en el package.json. En proyectos nuevos se recomienda ESM.
Un "módulo" es simplemente un archivo que exporta cosas (funciones, objetos, valores) para que otros archivos las usen. Node tiene dos sistemas para esto:
CommonJS (CJS) — el original de Node:
- Para exportar:
module.exportsoexports. - Para importar:
require(). - La carga es síncrona: cuando haces
require, Node lee y ejecuta ese archivo en ese instante, deteniendo la ejecución hasta terminar. Esto funciona bien porque los archivos están en disco local. requirees dinámico: puedes llamarlo dentro de unifo a mitad de una función.
ES Modules (ESM) — el estándar moderno de JavaScript (el mismo del navegador):
- Para exportar:
exportyexport default. - Para importar:
import. - La carga es asíncrona: el motor analiza primero todas las importaciones antes de ejecutar. Por eso
import(la forma estática) debe ir arriba del archivo, no dentro de unif. (Existeimport()dinámico, que sí devuelve una promesa y puede usarse en cualquier parte.) - Es el futuro: soporta
top-level awaity es compatible con navegadores.
Cómo activar ESM en Node:
- Usar la extensión
.mjsen tus archivos, o - Poner
"type": "module"en tupackage.json(así todos los.jsse tratan como ESM). En ese caso, si necesitas un archivo CommonJS puntual, usas la extensión.cjs.
¿Cuándo usar cada uno?
- ESM: proyectos nuevos, código que compartes con el frontend, cuando quieres
top-level await. Es la dirección recomendada hoy. - CommonJS: proyectos o librerías antiguas, o cuando dependes de paquetes que aún no ofrecen versión ESM. Sigue siendo totalmente válido y muy común.
// ===== CommonJS =====
// archivo: matematicas.cjs
function sumar(a, b) {
return a + b;
}
module.exports = { sumar }; // exportamos un objeto con la funcion
// archivo: app.cjs
const { sumar } = require("./matematicas.cjs"); // require es sincrono
console.log(sumar(2, 3)); // 5
// ===== ES Modules =====
// archivo: matematicas.mjs
export function sumar(a, b) {
return a + b;
}
export default function restar(a, b) {
return a - b;
}
// archivo: app.mjs
import restar, { sumar } from "./matematicas.mjs"; // import va arriba del archivo
console.log(sumar(2, 3)); // 5
console.log(restar(5, 2)); // 3
// Alternativa: activar ESM para todos los .js con package.json
{
"name": "mi-proyecto",
"type": "module"
}
Mezclar sintaxis sin darse cuenta: usar require() en un archivo que Node trata como ESM (porque tiene "type": "module"), lo que produce el error require is not defined in ES module scope. O al revés, usar import en un archivo CommonJS. Otro error frecuente es olvidar la extensión del archivo en los import de ESM: en Node, import { sumar } from "./matematicas" puede fallar; debes escribir "./matematicas.mjs".
"CommonJS es el sistema histórico de Node: usa require y module.exports, y carga los módulos de forma síncrona, así que require puede ir dentro de un if o una función. ES Modules es el estándar oficial de JavaScript: usa import y export, su carga es asíncrona y los imports estáticos deben ir arriba del archivo. Activo ESM con la extensión .mjs o poniendo type module en el package.json, y en ese caso uso .cjs para los archivos CommonJS puntuales. Para proyectos nuevos prefiero ESM porque es el estándar, se lleva bien con el frontend y soporta top-level await; CommonJS lo mantengo cuando trabajo con código o dependencias antiguas."
Tienes un package.json con "type": "module" y este archivo index.js. ¿Qué pasa al ejecutarlo?
const fs = require("fs");
console.log("hola");
Ver respuesta
Falla con un error parecido a: ReferenceError: require is not defined in ES module scope.
Como el package.json tiene "type": "module", Node trata el index.js como ESM, y en ESM no existe require. La solución es usar import fs from "fs"; (o import fs from "node:fs";), o bien renombrar el archivo a index.cjs si de verdad quieres usar CommonJS.