En esta página
Modulos ES
Qué son los módulos ES?
Los módulos ES (ESM) son el sistema de módulos nativo de JavaScript, estandarizado en ES2015. Permiten dividir el código en archivos independientes con sus propias dependencias y exportaciones.
Antes de los módulos ES, JavaScript no tenia un sistema de módulos nativo. Se usaban patrones como IIFE, CommonJS (require) y AMD. Los módulos ES los reemplazan a todos.
Caracteristicas principales
- Cada archivo es un módulo con su propio scope (no contamina el global)
- Las dependencias se declaran con import/export de forma explícita
- Se evaluan en modo estricto automaticamente
- Los imports son enlaces vivos (reflejan cambios del módulo exportador)
Exports
Named exports
Un módulo puede tener multiples named exports:
// utils.js
export function formatear(fecha) { /* ... */ }
export function validar(email) { /* ... */ }
export const VERSION = '1.0.0';Default export
Cada módulo puede tener un solo default export. Es útil cuando el módulo exporta una cosa principal:
// Logger.js
export default class Logger {
log(msg) { console.log(msg); }
}Cuando usar cada uno
| Tipo | Cuando usarlo |
|---|---|
| Named | Multiples utilidades, constantes, funciones |
| Default | Clases, componentes, una función principal |
Imports
// Named - nombres exactos, con llaves
import { sumar, restar } from './math.js';
// Default - nombre libre, sin llaves
import MiClase from './MiClase.js';
// Ambos
import MiClase, { utilidad } from './módulo.js';
// Renombrar
import { sumar as add } from './math.js';
// Todo como namespace
import * as Utils from './utils.js';Re-exports (barrels)
Un archivo index.js puede re-exportar desde multiples módulos, creando un punto de entrada único:
// features/index.js
export { UserList } from './user-list.js';
export { UserDetail } from './user-detail.js';
export { UserForm } from './user-form.js';Esto permite importar todo desde una sola ruta:
import { UserList, UserDetail, UserForm } from './features/index.js';Dynamic imports
import() como función retorna una promesa y permite cargar módulos bajo demanda. Es clave para:
- Lazy loading — Cargar código solo cuando se necesita
- Code splitting — Dividir el bundle en chunks más pequenios
- Carga condicional — Cargar módulos segun la plataforma o configuración
const boton = document.querySelector('#abrir-editor');
boton.addEventListener('click', async () => {
const { Editor } = await import('./editor.js');
const editor = new Editor();
editor.montar('#contenedor');
});Modulos en el navegador
Para usar módulos directamente en HTML:
<script type="module" src="app.js"></script>Los scripts de tipo module son diferidos automaticamente y se ejecutan en modo estricto. En la práctica, los bundlers (Vite, Webpack, esbuild) procesan los módulos para producción.
Práctica
- Crea un modulo con named exports: Crea un archivo
utils.jsque exporte dos funciones (capitalizarytruncar) y una constanteMAX_LONGITUD. Importalas en otro archivo y usalas. - Implementa un barrel export: Crea tres modulos pequenios y un archivo
index.jsque re-exporte todo. Importa desde el barrel y verifica que todas las exportaciones estan disponibles. - Usa dynamic import: Escribe un boton que al hacer click cargue un modulo de forma dinamica con
import()y ejecute una funcion del modulo cargado. Observa en la consola de red que el modulo se carga bajo demanda.
En la siguiente leccion exploraremos patrones modernos de JavaScript.
// === math.js ===
// Named exports
export function sumar(a, b) {
return a + b;
}
export function restar(a, b) {
return a - b;
}
export const PI = 3.14159;
// === user.js ===
// Default export (uno por archivo)
export default class User {
constructor(nombre, email) {
this.nombre = nombre;
this.email = email;
}
saludar() {
return `Hola, soy ${this.nombre}`;
}
}
// === constants.js ===
export const CONFIG = Object.freeze({
API_URL: 'https://api.ejemplo.com',
VERSION: '2.0.0',
MAX_RETRIES: 3,
});
export const ROLES = Object.freeze({
ADMIN: 'admin',
EDITOR: 'editor',
LECTOR: 'lector',
});
// === app.js ===
// Named imports
import { sumar, restar, PI } from './math.js';
console.log(sumar(2, 3)); // 5
console.log(PI); // 3.14159
// Default import (nombre libre)
import User from './user.js';
const carlos = new User('Carlos', '[email protected]');
// Renombrar imports
import { sumar as add, restar as subtract } from './math.js';
// Importar todo como namespace
import * as MathUtils from './math.js';
console.log(MathUtils.sumar(1, 2));
console.log(MathUtils.PI);
// Re-exportar (barrels)
// === index.js ===
export { sumar, restar } from './math.js';
export { default as User } from './user.js';
export { CONFIG, ROLES } from './constants.js';
// Dynamic import (lazy loading)
async function cargarEditor() {
const módulo = await import('./editor.js');
const editor = new módulo.default();
editor.iniciar();
}
// Condicional
if (necesitaGraficos) {
const { renderChart } = await import('./charts.js');
renderChart(datos);
}
Inicia sesión para guardar tu progreso