Español

Explora las diferencias entre CommonJS y Módulos ES, los dos sistemas de módulos dominantes en JavaScript, con ejemplos prácticos.

Sistemas de módulos: CommonJS vs. Módulos ES - Una guía completa

En el mundo en constante evolución del desarrollo de JavaScript, la modularidad es una piedra angular para construir aplicaciones escalables y mantenibles. Históricamente, dos sistemas de módulos han dominado el panorama: CommonJS y Módulos ES (ESM). Comprender sus diferencias, ventajas y desventajas es crucial para cualquier desarrollador de JavaScript, ya sea que trabaje en el front-end con frameworks como React, Vue o Angular, o en el back-end con Node.js.

¿Qué son los sistemas de módulos?

Un sistema de módulos proporciona una forma de organizar el código en unidades reutilizables llamadas módulos. Cada módulo encapsula una pieza específica de funcionalidad y expone solo las partes que otros módulos necesitan usar. Este enfoque promueve la reutilización del código, reduce la complejidad y mejora la mantenibilidad. Piensa en los módulos como bloques de construcción; cada bloque tiene un propósito específico y puedes combinarlos para crear estructuras más grandes y complejas.

Beneficios de usar sistemas de módulos:

CommonJS: El estándar de Node.js

CommonJS surgió como el sistema de módulos estándar para Node.js, el popular entorno de tiempo de ejecución de JavaScript para el desarrollo del lado del servidor. Fue diseñado para abordar la falta de un sistema de módulos incorporado en JavaScript cuando Node.js se creó por primera vez. Node.js adoptó CommonJS como su forma de organizar el código. Esta elección tuvo un profundo impacto en cómo se construyeron las aplicaciones JavaScript en el lado del servidor.

Características clave de CommonJS:

Sintaxis de CommonJS:

Aquí tienes un ejemplo de cómo se usa CommonJS:

Módulo (math.js):

// math.js
function add(a, b) {
 return a + b;
}

function subtract(a, b) {
 return a - b;
}

module.exports = {
 add: add,
 subtract: subtract
};

Uso (app.js):

// app.js
const math = require('./math');

console.log(math.add(5, 3)); // Output: 8
console.log(math.subtract(10, 4)); // Output: 6

Ventajas de CommonJS:

Desventajas de CommonJS:

Módulos ES (ESM): El sistema de módulos JavaScript estandarizado

Los Módulos ES (ESM) son el sistema de módulos estandarizado oficial para JavaScript, introducido con ECMAScript 2015 (ES6). Su objetivo es proporcionar una forma consistente y eficiente de organizar el código tanto en Node.js como en el navegador. ESM aporta soporte de módulos nativos al propio lenguaje JavaScript, eliminando la necesidad de bibliotecas externas o herramientas de compilación para gestionar la modularidad.

Características clave de los módulos ES:

Sintaxis de los módulos ES:

Aquí tienes un ejemplo de cómo se usan los módulos ES:

Módulo (math.js):

// math.js
export function add(a, b) {
 return a + b;
}

export function subtract(a, b) {
 return a - b;
}

// O, alternativamente:
// function add(a, b) {
//  return a + b;
// }
// function subtract(a, b) {
//  return a - b;
// }
// export { add, subtract };

Uso (app.js):

// app.js
import { add, subtract } from './math.js';

console.log(add(5, 3)); // Output: 8
console.log(subtract(10, 4)); // Output: 6

Exportaciones con nombre vs. Exportaciones predeterminadas:

Los módulos ES admiten tanto exportaciones con nombre como predeterminadas. Las exportaciones con nombre te permiten exportar múltiples valores desde un módulo con nombres específicos. Las exportaciones predeterminadas te permiten exportar un solo valor como la exportación predeterminada de un módulo.

Ejemplo de exportación con nombre (utils.js):

// utils.js
export function formatCurrency(amount, currencyCode) {
 // Formatea la cantidad de acuerdo con el código de la moneda
 // Ejemplo: formatCurrency(1234.56, 'USD') podría devolver '$1,234.56'
 // La implementación depende del formato deseado y de las bibliotecas disponibles
 return new Intl.NumberFormat('en-US', { style: 'currency', currency: currencyCode }).format(amount);
}

export function formatDate(date, locale) {
 // Formatea la fecha de acuerdo con la configuración regional
 // Ejemplo: formatDate(new Date(), 'fr-CA') podría devolver '2024-01-01'
 return new Intl.DateTimeFormat(locale).format(date);
}
// app.js
import { formatCurrency, formatDate } from './utils.js';

const price = formatCurrency(19.99, 'EUR'); // Europa
const today = formatDate(new Date(), 'ja-JP'); // Japón

console.log(price); // Output: €19.99
console.log(today); // Output: (varía según la fecha)

Ejemplo de exportación predeterminada (api.js):

// api.js
const api = {
 fetchData: async (url) => {
 const response = await fetch(url);
 return response.json();
 }
};

export default api;
// app.js
import api from './api.js';

api.fetchData('https://example.com/data')
 .then(data => console.log(data));

Ventajas de los módulos ES:

Desventajas de los módulos ES:

CommonJS vs. Módulos ES: Una comparación detallada

Aquí tienes una tabla que resume las principales diferencias entre CommonJS y Módulos ES:

Característica CommonJS Módulos ES
Sintaxis de importación require() import
Sintaxis de exportación module.exports export
Carga Síncrona Asíncrona (en navegadores), Síncrona/Asíncrona en Node.js
Análisis estático No
Soporte nativo del navegador No
Caso de uso principal Node.js (históricamente) Navegadores y Node.js (moderno)

Ejemplos prácticos y casos de uso

Ejemplo 1: Creación de un módulo de utilidad reutilizable (Internacionalización)

Digamos que estás creando una aplicación web que necesita admitir varios idiomas. Puedes crear un módulo de utilidad reutilizable para gestionar la internacionalización (i18n).

Módulos ES (i18n.js):

// i18n.js
const translations = {
 'en': {
 'greeting': 'Hello, world!'
 },
 'fr': {
 'greeting': 'Bonjour, le monde !'
 },
 'es': {
 'greeting': '¡Hola, mundo!'
 }
};

export function getTranslation(key, language) {
 return translations[language][key] || key;
}
// app.js
import { getTranslation } from './i18n.js';

const language = 'fr'; // Ejemplo: El usuario seleccionó francés
const greeting = getTranslation('greeting', language);
console.log(greeting); // Output: Bonjour, le monde !

Ejemplo 2: Creación de un cliente de API modular (API REST)

Al interactuar con una API REST, puedes crear un cliente de API modular para encapsular la lógica de la API.

Módulos ES (apiClient.js):

// apiClient.js
const API_BASE_URL = 'https://api.example.com';

async function get(endpoint) {
 const response = await fetch(`${API_BASE_URL}${endpoint}`);
 if (!response.ok) {
 throw new Error(`HTTP error! status: ${response.status}`);
 }
 return response.json();
}

async function post(endpoint, data) {
 const response = await fetch(`${API_BASE_URL}${endpoint}`, {
 method: 'POST',
 headers: {
 'Content-Type': 'application/json'
 },
 body: JSON.stringify(data)
 });
 if (!response.ok) {
 throw new Error(`HTTP error! status: ${response.status}`);
 }
 return response.json();
}

export { get, post };
// app.js
import { get, post } from './apiClient.js';

get('/users')
 .then(users => console.log(users))
 .catch(error => console.error('Error fetching users:', error));

post('/users', { name: 'John Doe', email: 'john.doe@example.com' })
 .then(newUser => console.log('New user created:', newUser))
 .catch(error => console.error('Error creating user:', error));

Migración de CommonJS a Módulos ES

La migración de CommonJS a Módulos ES puede ser un proceso complejo, especialmente en bases de código grandes. Aquí tienes algunas estrategias a considerar:

Node.js y Módulos ES:

Node.js ha evolucionado para admitir completamente los Módulos ES. Puedes usar Módulos ES en Node.js mediante:

Elegir el sistema de módulos correcto

La elección entre CommonJS y Módulos ES depende de tus necesidades específicas y del entorno en el que estás desarrollando:

Conclusión

Comprender las diferencias entre CommonJS y Módulos ES es esencial para cualquier desarrollador de JavaScript. Si bien CommonJS ha sido históricamente el estándar para Node.js, los Módulos ES se están convirtiendo rápidamente en la opción preferida tanto para navegadores como para Node.js debido a su naturaleza estandarizada, beneficios de rendimiento y soporte para análisis estático. Al considerar cuidadosamente las necesidades de tu proyecto y el entorno en el que estás desarrollando, puedes elegir el sistema de módulos que mejor se adapte a tus requisitos y crear aplicaciones JavaScript escalables, mantenibles y eficientes.

A medida que el ecosistema de JavaScript continúa evolucionando, mantenerse informado sobre las últimas tendencias y mejores prácticas del sistema de módulos es crucial para el éxito. Sigue experimentando con CommonJS y Módulos ES, y explora las diversas herramientas y técnicas disponibles para ayudarte a crear código JavaScript modular y mantenible.