La modularización en JavaScript es una técnnica fundamental para organizar el código en fragmentos independientes y reutilizables. Este enfoque permite gestionar las dependencias de manera eficiente, evitando colisiones en el espacio de nombres global y mejorando significativamente la escalabilidad del software.
Evolución de los Ssitemas de Módulos
- Patrón IIFE: Utiliza expresiones de función ejecutadas inmediatamente para crear un entorno privado, exponiendo solo lo necesario a través de un objeto global.
- CommonJS: El estándar adoptado por Node.js. Se basa en
require()para importar ymodule.exportspara exportar, funcionando de manera síncrona. - AMD (Asynchronous Module Definition): Diseñado para navegadores, permite la carga asíncrona de dependencias mediante la función
define(). - ES6 Modules (ESM): El estándar oficial de ECMAScript. Introduce
importyexport, permitiendo el análisis estático y optimizaciones como el tree-shaking.
1. Exportaciones por Defecto (export default)
Este método se utiliza para exportar un único valor principal desde un archivo. Al importar, no es necesario usar llaves y se puede asignar cualquier nombre al elemento importado.
// configuracion.js
const puerto = 8080;
export default puerto;
// main.js
import puertoServidor from './configuracion';
// Se puede renombrar libremente al importar
También es posible exportar objetos complejos de forma predeterminada:
// utilidades.js
const version = "1.0.0";
const entorno = "produccion";
const inicializar = () => console.log("Sistema iniciado");
export default {
version,
entorno,
inicializar
}
// app.js
import core from './utilidades';
core.inicializar();
2. Exportaciones Nombradas (export)
Permiten exportar múltiples elementos desde un mismo módulo. Para importarlos, se requiere el uso de llaves {} y los nombres deben coincidir exactamente, a menos que se use un alias.
// acciones.js
export const NIVEL_LOG = 'info';
export const encender = () => {
console.log('Dispositivo encendido');
}
export function apagar() {
console.log('Dispositivo apagado');
}
// importacion.js
import { NIVEL_LOG as nivel, encender, apagar } from './acciones';
// O importar todo como un objeto:
// import * as gestor from './acciones';
Otra forma de declarar exportaciones nombradas es al final del archivo:
const nombreApp = "AdminPanel";
const timeout = 5000;
function obtenerConfig() {
return { nombreApp, timeout };
}
export { nombreApp, timeout, obtenerConfig };
3. Uso Combinado de Exportaciones
Un módulo puede contener una exportación por defecto y varias exportaciones nombradas simultáneamente.
// usuario.js
const usuarioPrincipal = "Admin";
export const idSesion = "998877";
export default usuarioPrincipal;
// login.js
import usuario, { idSesion } from "./usuario";
console.log(`Usuario: ${usuario}, Sesión: ${idSesion}`);
4. Sistema de Módulos CommonJS
En entornos como Node.js, es común el uso de module.exports. Es importante notar que exports es simplemente una referencia inicial a module.exports.
// database.js
const conectar = () => { /* lógica */ };
const desconectar = () => { /* lógica */ };
module.exports = { conectar, desconectar };
// index.js
const { conectar } = require('./database');
Uso de exports individualmente:
// matetica.js
exports.sumar = (a, b) => a + b;
exports.restar = (a, b) => a - b;
// cliente.js
const mates = require('./matetica');
console.log(mates.sumar(10, 5));
5. Diferencias Clave: CommonJS vs ES6 Modules
- Tiempo de carga: ES6 se resuelve en tiempo de compilación (estático), mientras que CommonJS se resuelve en tiempo de ejecución (dinámico).
- Sintaxis: ESM utiliza
import/export; CommonJS utilizarequire/module.exports. - Hoisting: Las importaciones de ES6 se elevan al principio del archivo;
requireno. - Modo de carga:
require()es síncrono.importes asíncrono y gestiona fases de resolución de dependencias. - Copia vs Referencia: CommonJS exporta una copia de los valores (con caché). ES6 exporta una referencia dinámica y de solo lectura al valor original.
- Variable 'this': En CommonJS,
thisen el nivel superior apunta al módulo; en ES6 esundefined. - Modo Estricto: ES6 Modules operan siempre bajo
'use strict'de forma nativa.
// Comportamiento en ES6
const miFuncion = () => {
variableGlobalNoDeclarada = 50; // Error: variable no definida
};
export default miFuncion;
// Comportamiento en CommonJS
exports.miFuncion = () => {
variableGlobalNoDeclarada = 50; // No fallará a menos que se active "use strict" manualmente
};