2026 Es el Ano de la Adopcion Completa de ES Modules en JavaScript
Hola HaWkers, despues de anos de transicion, 2026 marca el ano en que ES Modules (ESM) finalmente alcanza adopcion completa en el ecosistema JavaScript. Node.js ahora permite importar ESM desde CommonJS, bibliotecas principales estan dejando de soportar CJS, y la comunidad esta convergiendo hacia un unico sistema de modulos.
Si todavia estas usando CommonJS en tus proyectos, este es el momento de migrar. Vamos a entender por que este cambio es tan importante y como hacer la transicion de forma segura.
Lo Que Cambio en 2026
El Giro Definitivo
Varios factores convergieron para hacer de 2026 el ano del ESM.
Hitos importantes:
- Node.js 24 LTS: Soporte completo a ESM como estandar
- Node.js 22+: Permite
import()de ESM dentro de archivos CJS - npm trends: 70%+ de las nuevas bibliotecas son ESM-only
- Principales bibliotecas: chalk, execa, got, ora dejaron CJS
Comparacion del ecosistema:
| Ano | Bibliotecas ESM-only | Bibliotecas Dual | CJS-only |
|---|---|---|---|
| 2020 | 5% | 15% | 80% |
| 2022 | 15% | 30% | 55% |
| 2024 | 35% | 40% | 25% |
| 2026 | 60% | 30% | 10% |
Cita de un core maintainer de Node.js:
"Finalmente podemos decir que ES Modules es el camino estandar para JavaScript. La interoperabilidad con CommonJS esta lo suficientemente madura para que la transicion sea suave."
Por Que ES Modules Es Mejor
Ventajas Tecnicas
ES Modules ofrece beneficios concretos sobre CommonJS.
1. Import estatico y tree-shaking:
// CommonJS - importa todo
const _ = require('lodash');
const result = _.map([1, 2, 3], x => x * 2);
// ESM - importa solo lo necesario
import { map } from 'lodash-es';
const result = map([1, 2, 3], x => x * 2);
// Resultado: bundle 70% menor con ESM + tree-shaking2. Top-level await:
// ESM permite await en el nivel superior
const config = await fetch('/config.json').then(r => r.json());
const db = await connectDatabase(config.dbUrl);
export { db, config };
// CommonJS exigiria wrapper async o callbacks3. Resolucion de modulos mas predecible:
// ESM - siempre necesita la extension
import { helper } from './utils.js';
import data from './data.json' assert { type: 'json' };
// URLs e imports dinamicos
const module = await import(`./plugins/${pluginName}.js`);4. Compatibilidad con navegadores:
<!-- ESM funciona nativamente en el browser -->
<script type="module">
import { render } from './app.js';
render(document.getElementById('root'));
</script>
Como Migrar de CommonJS a ESM
Guia Paso a Paso
Migrar un proyecto existente requiere algunos pasos especificos.
Paso 1: Actualizar package.json
{
"name": "mi-proyecto",
"version": "1.0.0",
"type": "module",
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.cjs"
}
},
"engines": {
"node": ">=18.0.0"
}
}Paso 2: Renombrar archivos (si es necesario)
# Si no usa "type": "module", renombre a .mjs
mv src/index.js src/index.mjs
# O mantenga .js con "type": "module" en package.jsonPaso 3: Actualizar imports/exports
// Antes (CommonJS)
const express = require('express');
const { readFile } = require('fs').promises;
const myModule = require('./myModule');
module.exports = { app, server };
module.exports.helper = helper;
// Despues (ESM)
import express from 'express';
import { readFile } from 'fs/promises';
import myModule from './myModule.js'; // Note la extension
export { app, server };
export { helper };Paso 4: Manejar __dirname y __filename
// CommonJS tenia __dirname y __filename globales
// ESM necesita recrearlos
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Uso
const configPath = join(__dirname, 'config.json');
Casos Especiales en la Migracion
Lidiando Con Dependencias CommonJS
No todas las bibliotecas migraron a ESM.
Importando CJS en ESM:
// Importacion estandar funciona para la mayoria de los casos
import lodash from 'lodash'; // CJS
// Para named exports de CJS, puede necesitar:
import pkg from 'some-cjs-package';
const { namedExport } = pkg;
// O use createRequire para casos especiales
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const legacyLib = require('legacy-cjs-lib');Importando ESM en CJS (Node.js 22+):
// Ahora es posible en Node.js 22+
// archivo.cjs o archivo sin "type": "module"
async function main() {
// Import dinamico funciona
const { something } = await import('esm-only-package');
// O en el tope del archivo con la nueva feature
}
// Node.js 22+ tambien soporta require() de ESM sincrono
// en algunos casosDual package (soportar ambos):
{
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
},
"./utils": {
"import": "./dist/utils.mjs",
"require": "./dist/utils.cjs"
}
}
}
Herramientas Para la Migracion
Automatizando el Proceso
Varias herramientas ayudan en la migracion.
1. cjs-to-esm
# Convierte archivos CJS a ESM
npx cjs-to-esm src/**/*.js
# Opciones
npx cjs-to-esm --ext=.mjs src/**/*.js2. ESLint para validacion
// .eslintrc.js
export default {
parserOptions: {
sourceType: 'module',
ecmaVersion: 2026,
},
rules: {
// Garantiza uso correcto de ESM
'import/extensions': ['error', 'always'],
'import/no-commonjs': 'error',
},
};3. TypeScript con ESM
// tsconfig.json
{
"compilerOptions": {
"module": "NodeNext",
"moduleResolution": "NodeNext",
"target": "ES2022",
"outDir": "./dist",
"declaration": true
}
}4. Vite y bundlers modernos
// vite.config.js - ESM por defecto
import { defineConfig } from 'vite';
export default defineConfig({
build: {
lib: {
entry: './src/index.js',
formats: ['es', 'cjs'],
fileName: (format) => `index.${format === 'es' ? 'mjs' : 'cjs'}`
}
}
});
Problemas Comunes y Soluciones
Troubleshooting
Algunos problemas frecuentes en la migracion.
Error: "require is not defined"
// Problema: usando require() en archivo ESM
// Solucion: usar import o createRequire
// Incorrecto
const fs = require('fs'); // Error en ESM
// Correcto
import fs from 'fs';
// o
import { createRequire } from 'module';
const require = createRequire(import.meta.url);Error: "Cannot use import statement outside a module"
// Problema: archivo no esta siendo tratado como ESM
// Soluciones:
// 1. Agregar "type": "module" en package.json
// 2. Renombrar el archivo a .mjs
// 3. Usar la flag --experimental-vm-modules (tests)Error: "ERR_MODULE_NOT_FOUND"
// Problema: falta extension en el import
// ESM requiere extensiones explicitas
// Incorrecto
import { helper } from './utils';
// Correcto
import { helper } from './utils.js';Problema con JSON imports:
// ESM requiere assertion para JSON
import data from './data.json' assert { type: 'json' };
// O use createRequire
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const data = require('./data.json');
El Impacto en el Ecosistema
Cambios en Bibliotecas Populares
Muchas bibliotecas ya migraron o estan migrando.
Bibliotecas que dejaron CommonJS:
| Biblioteca | Version ESM-only | Alternativa CJS |
|---|---|---|
| chalk | 5.0+ | chalk@4 |
| execa | 6.0+ | execa@5 |
| got | 12.0+ | got@11 |
| ora | 6.0+ | ora@5 |
| globby | 13.0+ | globby@12 |
| node-fetch | 3.0+ | node-fetch@2 |
Estrategias de las bibliotecas:
- ESM-only: Fuerza usuarios a migrar (chalk, got)
- Dual package: Soporta ambos (axios, lodash)
- CJS con wrapper ESM: Mantiene CJS, exporta ESM (express)
Recomendacion:
Para nuevos proyectos, use ESM desde el inicio. Para proyectos existentes, planee la migracion gradualmente, comenzando por los modulos menos criticos.
Beneficios de Performance
Por Que ESM Es Mas Rapido
El cambio a ESM trae ganancias de performance.
Tree-shaking efectivo:
// Comparacion de tamano de bundle (ejemplo real)
// Proyecto usando lodash
// CommonJS: 72KB (lodash entero)
// ESM con tree-shaking: 4KB (solo funciones usadas)Carga paralela en el browser:
// ESM permite carga paralela de dependencias
// El browser resuelve el grafo de imports y carga en paralelo
// Resultado: tiempo de carga 30-50% menor
// para aplicaciones con muchos modulosCache mas eficiente:
// Cada modulo ESM puede ser cacheado independientemente
// Cambios en un modulo no invalidan otros
// Beneficio en CI/CD y builds incrementalesConclusion
2026 marca la consolidacion de ES Modules como el estandar de JavaScript. La transicion puede parecer trabajosa, pero los beneficios en terminos de performance, compatibilidad y developer experience justifican el esfuerzo.
Puntos principales:
- ES Modules es ahora el estandar de facto de JavaScript
- Node.js 22+ permite interoperabilidad completa
- Migrar requiere atencion a extensiones y sintaxis
- Herramientas automatizan gran parte del proceso
- Beneficios incluyen tree-shaking y mejor performance
Recomendaciones:
- Comienza nuevos proyectos con ESM
- Planea migracion de proyectos existentes
- Usa herramientas de conversion automatica
- Testea extensivamente despues de migracion
- Manten dual package si es necesario para compatibilidad
Para mas sobre JavaScript moderno, lee: ES2026: Nuevos Recursos que Van a Transformar Como Escribimos JavaScript.

