Volver al blog

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-shaking

2. 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 callbacks

3. 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.json

Paso 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 casos

Dual 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/**/*.js

2. 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:

  1. ESM-only: Fuerza usuarios a migrar (chalk, got)
  2. Dual package: Soporta ambos (axios, lodash)
  3. 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 modulos

Cache mas eficiente:

// Cada modulo ESM puede ser cacheado independientemente
// Cambios en un modulo no invalidan otros

// Beneficio en CI/CD y builds incrementales

Conclusion

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:

  1. ES Modules es ahora el estandar de facto de JavaScript
  2. Node.js 22+ permite interoperabilidad completa
  3. Migrar requiere atencion a extensiones y sintaxis
  4. Herramientas automatizan gran parte del proceso
  5. 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.

Vamos con todo! 🦅

Comentarios (0)

Este artículo aún no tiene comentarios 😢. ¡Sé el primero! 🚀🦅

Añadir comentarios