Guía completa sobre los módulos export e import en JavaScript.

¿Harto del caos en tu código JavaScript? ¡Organízalo como un profesional! Antes, tu JavaScript era un archivo gigante y desordenado. Hoy, los Módulos (con export e import) te permiten dividir tu código en piezas manejables, dándote claridad, reutilización y control total. Descubre qué son, para qué sirven con ejemplos claros, y los enormes beneficios de esta práctica esencial para todo desarrollador. ¡Transforma tu código ahora!

modulos export import en javascript

1. ¿Que son los módulos?

Un módulo es un archivo JavaScript que puede exportar piezas específicas de su código (variables, funciones, clases, etc.) para que otros módulos puedan importarlas y utilizarlas.

Vamos desde el inicio……JavaScript ha evolucionado enormemente desde sus inicios como un simple lenguaje para dar interactividad a las páginas web. Con el tiempo, se ha convertido en la base de aplicaciones complejas, tanto en el navegador como en el servidor (con Node.js). Sin embargo, a medida que la escala de los proyectos JavaScript crecía, surgía un desafío fundamental: cómo organizar y gestionar eficientemente grandes volúmenes de código.

🚨El Problema del pasado: Un «Gran archivo JS»

En las primeras épocas de JavaScript, la práctica común era colocar todo el código en un único archivo JavaScript o enlazar múltiples archivos <script> directamente en el HTML. Si bien esto era funcional para pequeños scripts, rápidamente se convertía en una pesadilla de mantenimiento para proyectos más ambiciosos.

Imagina tener miles de líneas de código en un solo archivo. Rápidamente te encontrarías con problemas como:

✅ Contaminación del Ámbito Global
Todas las variables y funciones declaradas en el archivo se volvían accesibles desde cualquier otro lugar del código. Esto aumentaba drásticamente el riesgo de colisiones de nombres y efectos secundarios inesperados, haciendo que el código fuera frágil y difícil de depurar.
✅ Mantenimiento engorroso
Encontrar una función específica o entender cómo interactúan las diferentes partes del código en un archivo gigante era como buscar una aguja en un pajar. Cualquier pequeño cambio podía tener repercusiones impredecibles.
✅ Falta de reutilización
Reutilizar una pieza de código en otro proyecto significaba copiar y pegar, lo que llevaba a duplicidad y a un código inconsistente.

Era evidente que, para que JavaScript pudiera escalar y soportar la complejidad de las aplicaciones modernas, necesitaba una forma más robusta de estructurar y gestionar el código.

🚀La solución moderna: Módulos JavaScript (export e import)

Aquí es donde entran en juego los Módulos JavaScript, introducidos formalmente en la especificación ECMAScript 2015 (ES6). Los módulos proporcionan un sistema estandarizado y eficiente para dividir tu código JavaScript en archivos separados e independientes, cada uno con su propio ámbito.

Como dijimos en un comienzo, un módulo es un archivo JavaScript que puede exportar piezas específicas de su código (variables, funciones, clases, etc.) para que otros módulos puedan importarlas y utilizarlas.

1.1. ¿Para qué sirven los módulos en JavaScript?

Los módulos JavaScript, junto con las palabras clave export e import, nos ofrecen beneficios fundamentales:

✅ Organización Superior
Permiten estructurar tu proyecto de forma lógica, agrupando funcionalidades relacionadas en sus propios archivos. Esto mejora drásticamente la legibilidad y facilita el mantenimiento a medida que tu aplicación crece.
✅ Encapsulación y Aislamiento
Cada módulo tiene su propio «espacio privado». Las variables y funciones declaradas dentro de un módulo no son accesibles desde el exterior a menos que se exporten explícitamente. Esto elimina la contaminación del ámbito global, previene colisiones de nombres y hace que el código sea más robusto y predecible.
✅ Reutilización Eficiente del Código
Puedes crear componentes, utilidades o servicios en un módulo y luego importarlos y utilizarlos en cualquier parte de tu aplicación, o incluso en diferentes proyectos. Esto fomenta el desarrollo de código modular y evita repetición gracias al enfoque DRY.
✅ Gestión Clara de Dependencias
Al ver las declaraciones import al inicio de un archivo, sabes de inmediato qué funcionalidades externas necesita ese módulo. Esto hace explícito el flujo de dependencias y mejora la comprensión del código.
✅ Optimización del Rendimiento
Las herramientas de construcción modernas como Webpack o Vite aprovechan la estructura modular para aplicar optimizaciones como tree shaking y minificación. Esto da como resultado aplicaciones más ligeras y rápidas de cargar.

En resumen, los módulos JavaScript transformaron la forma en que se construye el software en el ecosistema JavaScript. Pasamos de un enfoque monolítico y propenso a errores a una arquitectura modular, escalable y mantenible, permitiéndonos crear aplicaciones complejas con una eficiencia y una calidad sin precedentes. Comprender y dominar export e import es, sin duda, un paso esencial para cualquier desarrollador JavaScript profesional.

2. Ejemplo usando los módulos export e import.

  1. Ejemplo de como era antes (sin módulos):
  2. Ejemplo: JavaScript moderno con módulos (export e import)

2.1. Ejemplo de como era antes (sin módulos):

En este modelo, todo el código JavaScript residía en un único archivo o en múltiples archivos enlazados directamente, donde todas las variables y funciones vivían en el ámbito global.

1. ESTRUCTURA DE ARCHIVOS:

Para este ejemplo, esta es la estructura de archivos que deberíamos introducir por ejemplo en un editor de códigos como VSCode.

mi-proyecto-modulos/
├── index.html
├── js/
│   ├── app.js

Aqui tenemos el archivo index.html (donde colocaremos todo nuestro HTML), y un unico archivo app.js para los códigos JavaScript.

2. LA ESTRUCTURA HTML (index.html)

Esta es una estructura HTML básica. Donde, al final del <body>, justo antes de la etiqueta de cierre, enlazamos el archivo JS al HTML (app.js).

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Ejemplo JS Tradicional</title>
</head>
<body>
    <h1>Bienvenido al Mundo Tradicional de JavaScript</h1>
    <p id="mensaje"></p>

    <script src="app.js"></script> // En esta línea estamos enlazando al JavaScript
</body>
</html>
Lenguaje del código: HTML, XML (xml)

3. EL CÓDIGO JavaScript en el archivo (app.js)

Aquí es donde reside toda nuestra lógica JavaScript. Observa que las variables y funciones se declaran directamente, y son accesibles en todo el archivo (y potencialmente desde el ámbito global del navegador).

// app.js

// 1. Una variable global
var nombreUsuario = "Visitante";

// 2. Una función global
function saludar() {
    var horaActual = new Date().getHours();
    var saludo;

    if (horaActual < 12) {
        saludo = "Buenos días";
    } else if (horaActual < 18) {
        saludo = "Buenas tardes";
    } else {
        saludo = "Buenas noches";
    }

    return `${saludo}, ${nombreUsuario}!`;
}

// 3. Otra función global que actualiza el DOM
function mostrarMensajeEnHTML() {
    var elementoMensaje = document.getElementById("mensaje");
    if (elementoMensaje) {
        elementoMensaje.textContent = saludar();
    }
}

// 4. Se ejecuta la función al cargar el script
mostrarMensajeEnHTML();

// 5. Un ejemplo de cómo otra parte del script (o incluso otro script enlazado)
// podría accidentalmente sobrescribir una variable global:
// var nombreUsuario = "Administrador"; // ¡Esto cambiaría el valor original sin previo aviso!
// console.log("Después de la posible sobrescritura:", saludar());Lenguaje del código: JavaScript (javascript)

NOTA!!!! Si te animas y deseas ver el resultado de este ejemplo y de todos los que iremos proporcionando directamente desde tu PC, te invito a seguir estos pasos.

  1. Primero, revisa el punto 5 del siguiente artículo sobre como usar e instalar VSCode (este es el editor de código mas usado), donde encontrarás los pasos para crear la estructura necesaria para visualizar una página desde tu navegador predeterminado.
  2. Si entendiste correctamente este paso anterior, sabrás donde colocar el código script que te acabamos de proporcionar (arriba). Ahora, puedes visualizar el resultado, para ello puedes hacer lo siguiente:
    • Una vez abierta y visualizada la página, abre la consola del navegador presionando la tecla F12.
    • Ahora, dirígete a la pestaña que dice Console, y desde aquí podrás ver el resultado del script que hayamos introducido anteriormente.
  3. No te preocupes, estos pasos son más simples de lo que parecen!!!! Entonces… cada vez que dejemos un código de ejemplo como éste, puedes seguir estos pasos y ver los resultados por ti mismo. ¡Ojalá te animes!!!!

Link para descargar el editor de código Visual Studi Code!!

4. Cómo funciona este ejemplo

  1. Carga del HTML: El navegador carga el index.html.
  2. Enlace del Script: Cuando llega a la línea <script src="app.js"></script>, el navegador descarga y ejecuta el contenido de app.js.
  3. Ámbito Global: Todas las declaraciones (nombreUsuario, saludar, mostrarMensajeEnHTML) se convierten en propiedades del objeto window (en el navegador) o del ámbito global de Node.js. Esto significa que son accesibles desde cualquier lugar del script o incluso desde la consola del navegador.
  4. Ejecución Directa: Las funciones se llaman directamente, y el código se ejecuta de arriba hacia abajo tan pronto como el script se carga.

⚠️EL PROBLEMA ILUSTRADO:

La sección comentada al final de app.js (var nombreUsuario = "Administrador";) destaca el principal problema: la contaminación del ámbito global. Si tuvieras otro archivo JavaScript enlazado en tu HTML que también declarara una variable nombreUsuario, la última en cargarse sobrescribiría a las anteriores sin aviso, llevando a comportamientos impredecibles y errores difíciles de rastrear en aplicaciones grandes.

Este es el punto de partida. En el siguiente paso, veremos cómo los módulos resuelven estos desafíos.

2.2. Ejemplo: JavaScript moderno con módulos (export e import)

En este ejemplo, dividiremos la lógica en dos archivos JavaScript: utils.js (que exportará funcionalidades) y app.js (que las importará y las usará). El HTML solo necesitará enlazar el archivo principal app.js, indicando que es un módulo.

1. ESTRUCTURA DE ARCHIVOS:

mi-proyecto-modulos/
├── index.html
├── js/
│   ├── app.js
│   ├── utils.js

Aquí , a diferencia del ejemplo 2.1. tenemos el archivo index.html (donde colocaremos todo nuestro HTML), y DOS archivos para los códigos JavaScript; app.js y utils.js)

2. LA ESTRUCTURA HTML (index.html)

Esta es una estructura HTML básica. Y al final del <body>, justo antes de la etiqueta de cierre, enlazamos nuestro archivo JavaScript (app.js que a su vez, importa otro archivo)

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Ejemplo JS Moderno con Módulos</title>
</head>
<body>
    <h1>Bienvenido al Mundo Moderno de JavaScript con Módulos</h1>
    <p id="mensaje"></p>

    <script type="module" src="app.js"></script>
</body>
</html>Lenguaje del código: HTML, XML (xml)

IMPORTANTE! Para poder usar import y export en el navegador, tenemos que indicarle al navegador que el script es un módulo. Esto se hace agregando type="module" en la etiqueta <script> dentro del HTML.

2. El Archivo de Utilidades (utils.js)

Este archivo contendrá nuestras funciones y variables que queremos exportar para que otros módulos las utilicen. Observa el uso de la palabra clave export (ampliamos en punto 3) delante de cada elemento que deseamos hacer público.

// utils.js

// Exportación nombrada de una variable
export const DEFAULT_USER_NAME = "Visitante Módulo";

// Exportación nombrada de una función
export function obtenerSaludoBasadoEnHora() {
    const horaActual = new Date().getHours();
    let saludo;

    if (horaActual < 12) {
        saludo = "Buenos días";
    } else if (horaActual < 18) {
        saludo = "Buenas tardes";
    } else {
        saludo = "Buenas noches";
    }

    return saludo;
}

// Exportación por defecto de una función principal para el mensaje
// Solo puede haber una exportación por defecto por archivo
export default function crearMensajeCompleto(nombre) {
    const saludoParte = obtenerSaludoBasadoEnHora(); // Función importada dentro de este mismo módulo
    return `${saludoParte}, ${nombre || DEFAULT_USER_NAME}!`;
}

// Importante: Fuera de un módulo, DEFAULT_USER_NAME, obtenerSaludoBasadoEnHora,
// y crearMensajeCompleto no existirían en el ámbito global del navegador
// a menos que sean explícitamente importados.
Lenguaje del código: JavaScript (javascript)

3. El archivo principal de la aplicación (app.js)

Este archivo será el punto de entrada de nuestra lógica JavaScript. Aquí es donde importaremos (en punto 4 ampliamos sobre el uso de import) las funcionalidades que necesitamos de utils.js para construir nuestro mensaje y actualizar el HTML.

// app.js

// Importación nombrada: Se usan llaves {} y el nombre exacto de lo exportado.
import { DEFAULT_USER_NAME } from './utils.js';

// Importación por defecto: No se usan llaves {} y puedes darle el nombre que quieras.
// Aquí, 'crearMensajeCompleto' fue la exportación por defecto en utils.js,
// y la importamos como 'generarMensaje' para este archivo.
import generarMensaje from './utils.js';

// (Opcional) Puedes importar todo lo exportado con nombre como un objeto:
// import * as utils from './utils.js';
// const mensaje = utils.default("María"); // Acceso a la exportación por defecto
// console.log(utils.DEFAULT_USER_NAME); // Acceso a la exportación nombrada

function mostrarMensajeEnHTML() {
    const elementoMensaje = document.getElementById("mensaje");
    if (elementoMensaje) {
        // Usamos la función importada (que internamente usa DEFAULT_USER_NAME)
        elementoMensaje.textContent = generarMensaje("Desarrollador");
        // O podríamos usar directamente la variable importada:
        // elementoMensaje.textContent = generarMensaje(DEFAULT_USER_NAME);
    }
}

// Ejecutamos la función al cargar el script (este es el único script que HTML carga directamente)
mostrarMensajeEnHTML();

// Nota clave: Aquí no podemos acceder a 'obtenerSaludoBasadoEnHora' directamente
// a menos que también la importemos, ya que no es global.
// console.log(obtenerSaludoBasadoEnHora()); // Esto daría un error: ReferenceError
Lenguaje del código: JavaScript (javascript)

Cómo funcionan estos módulos:

  1. Carga del HTML: El navegador carga index.html.
  2. type="module": Al llegar a <script type="module" src="app.js"></script>, el navegador sabe que app.js es un módulo.
  3. Resolución de Importaciones: Antes de ejecutar app.js, el navegador escanea sus declaraciones import. Ve que app.js necesita cosas de ./utils.js. Automáticamente, el navegador descarga y procesa utils.js primero.
  4. Ejecución y Ámbitos Aislados:
    • utils.js: Se ejecuta en su propio ámbito de módulo. DEFAULT_USER_NAME, obtenerSaludoBasadoEnHora, y crearMensajeCompleto existen solo dentro de este módulo. Solo los elementos exportados estarán disponibles para otros módulos.
    • app.js: También se ejecuta en su propio ámbito. Las variables y funciones que importa (DEFAULT_USER_NAME, generarMensaje) se «vinculan» a las exportaciones correspondientes de utils.js.
  5. Uso Seguro: Ahora, en app.js, puedes usar generarMensaje y DEFAULT_USER_NAME sin preocuparte por conflictos de nombres con otros scripts o librerías que pudieras tener. Si otro módulo tuviera una función llamada generarMensaje, no habría conflicto porque cada una vive en su propio módulo.

NOTA! Este ejemplo demuestra cómo los módulos te permiten dividir tu aplicación en piezas manejables, con dependencias claras y, lo más importante, ¡sin contaminar el ámbito global! Este es el patrón que verás en prácticamente todos los proyectos modernos de JavaScript.

3. La declaración export.

  1. ¿Qué es export?
  2. Exportación con nombre (named export)
  3. Exportación agrupada (al final del archivo)
  4. Exportar con alias (renombrar al exportar)
  5. Exportación por defecto (default export)
  6. Diferencias clave entre export y export default
  7. Buenas prácticas al usar export

3.1. ¿Qué es export?

export es una palabra clave de JavaScript que se usa para hacer público algo desde un archivo (módulo), para que otro archivo lo pueda importar y usarlo con import.

Tal como vimos en el ejemplo 2.2. que usamos export en el archivo utils.js para luego ser importado por el archivo app.js que es al archivo que definitivamente sincronizamos con el archivo .HTML

🤔¿Existen diferentes maneras en la que podemos usar esta declaración export? La respuesta es si, a continuación lo vemos…

3.2. Exportación con nombre (named export)

Las exportaciones nombradas te permiten exportar varios valores o funcionalidades desde un mismo archivo de módulo. Cuando otro módulo quiera usar estos elementos, deberá referirse a ellos por sus nombres exactos.

Sintaxis y ejemplos:

Puedes usar export directamente delante de la declaración de cualquier variable, función o clase:

📄 Ejemplo: utils.js

export const PI = 3.14;

export function sumar(a, b) {
  return a + b;
}

export class Persona {
  constructor(nombre) {
    this.nombre = nombre;
  }
}Lenguaje del código: JavaScript (javascript)

Después podes importarlos con su nombre exacto (o con alias si queres):

import { PI, sumar, Persona } from './utils.js';Lenguaje del código: JavaScript (javascript)

¿Qué sucede en este ejemplo?

  • Primero:
    • PI, sumar y Persona están siendo exportados individualmente con nombre.
    • Esto quiere decir que solo estarán disponibles para otros archivos si se importan por su nombre exacto (a menos que uses alias).
    • Cada uno de estos elementos no queda en el scope global; solo se puede acceder a ellos usando import.
  • Después:
    • Estamos importando por nombre los mismos valores que exportamos.
    • El uso de llaves {} indica que estamos haciendo un named import.
    • Si te equivocás en el nombre, da error (por ejemplo: import { Sumar } en lugar de sumar).

3.3. Exportación agrupada (al final del archivo)

Podes definir tus funciones o variables primero, y exportarlas todas juntas al final.

📄 Ejemplo: math.js

const multiplicar = (a, b) => a * b;
const dividir = (a, b) => a / b;

export { multiplicar, dividir };Lenguaje del código: JavaScript (javascript)

📥 En otro archivo:

import { multiplicar, dividir } from './math.js';Lenguaje del código: JavaScript (javascript)
  1. Primero:
    • Las funciones multiplicar y dividir se definen primero y luego se exportan juntas en una sola línea.
    • Esto permite mantener el código limpio y claro, especialmente cuando tenes muchas funciones en el archivo.
  2. Después:
    • Estamos importando las dos funciones exactamente como se llamaron al exportarlas.
    • Se pueden usar como si las hubiéramos definido en el mismo archivo.

3.4. Exportar con alias (renombrar al exportar)

Podemos cambiar el nombre de lo que exportamos si queremos evitar conflictos o clarificarlo.

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

export { restar as restaNumeros };Lenguaje del código: JavaScript (javascript)

📥 Y al importar:

import { restaNumeros } from './archivo.js';Lenguaje del código: JavaScript (javascript)
  1. Primero:
    • Estamos exportando restar, pero con un nuevo nombre externo: restaNumeros.
    • Internamente la función se llama restar, pero quien la importe la verá como restaNumeros.
  2. Después:
    • Usamos el nombre externo que se definió en la exportación.
    • Esto es útil cuando tenemos conflictos de nombre o queremos un nombre más claro para el contexto del archivo actual.

3.5. Exportación por defecto (default export)

A diferencia de las exportaciones nombradas, cada módulo puede tener solamente una exportación por defecto. Esta se considera el «elemento principal» o la funcionalidad más relevante que el módulo ofrece.

Sintaxis y Ejemplos:

La palabra clave export default se usa para especificar cuál es el valor predeterminado del módulo. No necesitas poner un nombre entre llaves al importarlo, ya que es el «por defecto».

Ejemplo: saludo.js

export default function saludar(nombre) {
  return `Hola, ${nombre}!`;
}Lenguaje del código: JavaScript (javascript)

📥 En otro archivo:

import saludar from './saludo.js';Lenguaje del código: JavaScript (javascript)
  1. Primero:
    • Estamos usando export default, que indica que este es el valor principal que exporta el archivo.
    • Sólo puede haber un export default por archivo.
    • No necesita importar usando {} y se puede importar con cualquier nombre.
  2. Después:
    • Importamos la función saludar sin llaves.
    • Podríamos haber escrito import miFuncion from './saludo.js' y funcionaría igual.
    • Esto es útil para exportar una única cosa importante por archivo (una clase principal, un componente, etc.).

3.6. Diferencias clave entre export y export default

Característicaexportexport default
¿Cuántos por archivo?MúltiplesSolo uno
¿Se importan con {}?No
¿Se puede renombrar al importar?Sí, con asSí, directamente (import otroNombre)
¿Obligatorio usar nombre original?Sí, salvo aliasNo, elegís el nombre libremente

3.7. Buenas prácticas al usar export

  • Usa export default cuando el archivo tenga una sola función principal (por ejemplo, una clase, o una función importante).
  • Usá export normal si queremos exportar múltiples utilidades (funciones, constantes, etc.).
  • Evitá mezclar export default y export en el mismo archivo, salvo que sepas bien lo que haces.
  • Dale nombres descriptivos a lo que exportas.

4. La declaración import.

  1. ¿Qué es import?
  2. Importar exportaciones nombradas
  3. Importar exportación por defecto
  4. Importar una combinación de exportaciones nombradas y por defecto.
  5. Importaciones dinámicas (import())
  6. En resumen en el uso de import:

4.1. ¿Qué es import?

La palabra clave import en JavaScript sirve para traer funciones, variables, objetos o clases exportadas desde otro archivo (módulo).
Se usa junto con export para conectar archivos y construir aplicaciones modulares y profesionales.

Cuando usas import, le estás diciendo a JavaScript: «Necesito esto de aquel archivo». Esto no solo hace que tu código sea más legible al mostrar sus dependencias explícitamente, sino que también garantiza que solo cargues el código que realmente necesitas.

Hay varias formas de importar, dependiendo de cómo se hayan exportado los elementos.

NOTA! Si bien en el punto anterior vimos como importar cada vez que dejamos un ejemplo usando export, aqui ampliaremos con mas ejemplo!!!!

4.2. Importar exportaciones nombradas

Cuando un módulo exporta múltiples elementos por su nombre (usando export const, export function, etc.), debes usar llaves {} y el nombre exacto de lo que estás importando.

Sintaxis básica:

import { nombreExportado1, nombreExportado2 } from './ruta/al/modulo.js';Lenguaje del código: JavaScript (javascript)

Ejemplo:

Imaginemos que tienes un archivo calculadora.js que exporta con varias funciones matemáticas:

// archivo: calculadora.js

export const PI = 3.14159; // Exportación nombrada de una constante

export function sumar(a, b) { // Exportación nombrada de una función
  return a + b;
}

export class MatematicasAvanzadas { // Exportación nombrada de una clase
  restar(a, b) {
    return a - b;
  }
}
Lenguaje del código: JavaScript (javascript)

Ahora, en tu archivo app.js, puedes importar y usar estas funcionalidades:

// archivo: app.js

// Importamos PI, la función sumar y la clase MatematicasAvanzadas
// de 'calculadora.js'. Los nombres deben coincidir exactamente.
import { PI, sumar, MatematicasAvanzadas } from './calculadora.js';

console.log(`El valor de PI es: ${PI}`); // Output: El valor de PI es: 3.14159
console.log(`La suma de 10 y 5 es: ${sumar(10, 5)}`); // Output: La suma de 10 y 5 es: 15

const calc = new MatematicasAvanzadas();
console.log(`La resta de 20 y 7 es: ${calc.restar(20, 7)}`); // Output: La resta de 20 y 7 es: 13
Lenguaje del código: JavaScript (javascript)

4.2.1. RENOMBRAR importaciones nombradas (con as):

A veces, el nombre de un elemento exportado puede chocar con otro nombre en tu archivo, o simplemente quieres usar un nombre más corto o más descriptivo localmente. Para eso, usas la palabra clave as.

Siguiendo las exportaciones del archivo calculadora.js:

// archivo: app.js

// Importamos 'sumar' como 'addNumeros' y 'MatematicasAvanzadas' como 'ClaseCalculo'.
import { sumar as addNumeros, MatematicasAvanzadas as ClaseCalculo } from './calculadora.js';

console.log(`La suma usando el alias es: ${addNumeros(8, 4)}`); // Output: La suma usando el alias es: 12

const miCalc = new ClaseCalculo();
console.log(`La resta usando la clase renombrada es: ${miCalc.restar(15, 3)}`); // Output: La resta usando la clase renombrada es: 12
Lenguaje del código: JavaScript (javascript)

4.2.2. Importar todo como un objeto (* as):

Si un módulo tiene muchas exportaciones nombradas y quieres acceder a todas ellas sin listarlas una por una, puedes importarlas como un objeto que las contenga a todas.

Siguiendo las exportaciones del archivo calculadora.js:

// archivo: app.js

// Importamos todas las exportaciones nombradas de 'calculadora.js'
// y las agrupamos bajo un alias de objeto llamado 'mathUtils'.
import * as mathUtils from './calculadora.js';

console.log(`PI desde el objeto: ${mathUtils.PI}`); // Output: PI desde el objeto: 3.14159
console.log(`Suma desde el objeto: ${mathUtils.sumar(2, 2)}`); // Output: Suma desde el objeto: 4
const otraCalc = new mathUtils.MatematicasAvanzadas();
console.log(`Resta desde el objeto: ${otraCalc.restar(10, 1)}`); // Output: Resta desde el objeto: 9
Lenguaje del código: JavaScript (javascript)

Importante: En entornos de navegador, siempre se debe incluir la extensión del archivo (.js, .mjs) en la ruta de importación (por ejemplo, ./calculadora.js). En Node.js, esto puede variar según la configuración (.mjs o "type": "module" en package.json).

4.3. Importar exportación por defecto

Cuando un módulo exporta un único elemento como por defecto (usando export default), no usas llaves {} al importarlo. Además, puedes darle cualquier nombre a la importación en tu archivo.

Sintaxis básica:

import NombreQueQuieras from './ruta/al/modulo.js';Lenguaje del código: JavaScript (javascript)

Ejemplo:

Supongamos que tienes un archivo usuario.js que exporta por defecto una clase Usuario:

// archivo: usuario.js

class Usuario { // Esta es la clase principal del módulo
  constructor(nombre) {
    this.nombre = nombre;
  }
  presentarse() {
    return `Hola, mi nombre es ${this.nombre}.`;
  }
}

export default Usuario; // Exportamos la clase Usuario como la por defecto
Lenguaje del código: JavaScript (javascript)

Ahora, en tu app.js, puedes importarla con el nombre que prefieras:

// archivo: app.js

// Importamos la exportación por defecto de 'usuario.js'.
// Le damos el nombre 'Persona' en este archivo.
import Persona from './usuario.js';

const juan = new Persona('Juan');
console.log(juan.presentarse()); // Output: Hola, mi nombre es Juan.

// Podríamos haberle dado otro nombre si quisiéramos:
import MiClaseDeUsuario from './usuario.js';
const ana = new MiClaseDeUsuario('Ana');
console.log(ana.presentarse()); // Output: Hola, mi nombre es Ana.
Lenguaje del código: JavaScript (javascript)

4.4. Importar una combinación de exportaciones nombradas y por defecto.

Es muy común que un módulo ofrezca un elemento principal (por defecto) y algunas utilidades adicionales (nombradas). Puedes importar ambas en una sola declaración.

Sintaxis:

import DefaultExport, { namedExport1, namedExport2 } from './ruta/al/modulo.js';Lenguaje del código: JavaScript (javascript)

Ejemplo:

Considera un archivo config.js que exporta:

  • Un objeto de configuración por defecto
  • Y algunas constantes nombradas
// archivo: config.js

export const IDIOMA_DEFECTO = 'es'; // Exportación nombrada
export const TEMA_DEFECTO = 'claro'; // Exportación nombrada

const configuracionGeneral = { // Objeto para la exportación por defecto
  apiUrl: 'https://api.example.com',
  timeout: 5000
};

export default configuracionGeneral; // Exportación por defecto
Lenguaje del código: JavaScript (javascript)

En app.js, puedes importar la configuración general como la exportación por defecto, y las constantes como exportaciones nombradas:

// archivo: app.js

// Importamos la exportación por defecto (configuracionGeneral) como 'appConfig',
// y las exportaciones nombradas IDIOMA_DEFECTO y TEMA_DEFECTO.
import appConfig, { IDIOMA_DEFECTO, TEMA_DEFECTO } from './config.js';

console.log(`API URL: ${appConfig.apiUrl}`); // Output: API URL: https://api.example.com
console.log(`Timeout: ${appConfig.timeout}ms`); // Output: Timeout: 5000ms

console.log(`Idioma por defecto: ${IDIOMA_DEFECTO}`); // Output: Idioma por defecto: es
console.log(`Tema por defecto: ${TEMA_DEFECTO}`); // Output: Tema por defecto: claro
Lenguaje del código: JavaScript (javascript)

4.5. Importaciones dinámicas (import())

Hasta ahora, todas las importaciones que hemos visto son «estáticas» (se procesan al inicio). Pero a veces, necesitas cargar un módulo solo cuando sea necesario, por ejemplo, al hacer clic en un botón o bajo cierta condición. Para esto, usamos la importación dinámica, que devuelve una Promesa.

Sintaxis:

import('./ruta/al/modulo.js')
  .then(modulo => {
    // Aquí puedes acceder a las exportaciones del módulo
  });

// O usando async/await
async function cargarModuloCondicionalmente() {
  const modulo = await import('./ruta/al/modulo.js');
  // Aquí puedes acceder a las exportaciones del módulo
}Lenguaje del código: JavaScript (javascript)

Ejemplo:

Imaginemos que tienes una función muy pesada en analisis.js que solo quieres cargar si el usuario hace clic en un botón:

// archivo: analisis.js

export function realizarAnalisisPesado() {
  console.log("Realizando un análisis de datos complejo...");
  // Simulación de una operación que tarda
  let resultado = 0;
  for (let i = 0; i < 100000000; i++) {
    resultado += Math.sqrt(i);
  }
  return `Análisis completado con resultado: ${resultado.toFixed(2)}`;
}

export const MENSAJE_ANALISIS_LISTO = "El análisis está listo.";
Lenguaje del código: JavaScript (javascript)

En tu app.js y index.html:

📌En el index.html tenemos el botón y la indexacción con el arvhicvo .js

<button id="botonAnalisis">Iniciar Análisis</button>
<div id="resultadoAnalisis"></div>
<script type="module" src="app.js"></script>Lenguaje del código: HTML, XML (xml)

📌En el app.js

// archivo: app.js

document.getElementById('botonAnalisis').addEventListener('click', async () => {
  const resultadoDiv = document.getElementById('resultadoAnalisis');
  resultadoDiv.textContent = 'Cargando módulo de análisis...';

  try {
    // Importación dinámica: el módulo 'analisis.js' solo se carga cuando se hace clic
    const analisisModulo = await import('./analisis.js');

    // Ahora que el módulo se ha cargado, podemos usar sus exportaciones
    const resultado = analisisModulo.realizarAnalisisPesado();
    resultadoDiv.textContent = analisisModulo.MENSAJE_ANALISIS_LISTO + " " + resultado;
  } catch (error) {
    resultadoDiv.textContent = `Error al cargar el módulo: ${error.message}`;
  }
});

console.log("App cargada, esperando clic en el botón para cargar análisis.");
Lenguaje del código: JavaScript (javascript)

En este caso, analisis.js no se carga cuando la página inicia, sino solo cuando el usuario interactúa con el botón. Esto es crucial para la optimización del rendimiento de grandes aplicaciones, cargando solo lo que se necesita, cuando se necesita.

4.6. En resumen en el uso de import:

Sintaxis¿Qué hace?
import { nombre } from './mod.js'Importa un valor con nombre
import { nombre as alias }Importa con otro nombre
import * as modulo from '...'Importa todo como un objeto
import valor from '...'Importa la exportación por defecto
import valor, { x, y } from ...Importa default + valores con nombre
import('./mod.js')Importación dinámica (promesa)

NOTA! El import es la pieza final del rompecabezas de los módulos, permitiéndote consumir y entrelazar la funcionalidad que has encapsulado y expuesto con export. Dominar ambas palabras clave te brinda el poder de construir aplicaciones JavaScript altamente organizadas, eficientes y fáciles de mantener.

5. Importar módulos en el navegador.

  1. ¿Qué significa “Importar módulos en el navegador”?
  2. ¿Cómo sincronizar los módulos con el index.html?
  3. Precauciones al sincronizar los módulos al index.html

5.1. ¿Qué significa “Importar módulos en el navegador”?

Una vez que hemos creado los archivos donde colocamos todo el JavaScript necesario con los export e import incorporados.

Ahora debemos sincronizarlo con el archivo index.html para que sus funcionalidades se hagan efectivas, a esta acción es lo que denominamos “Importar módulos en el navegador”.

Una vez hecho esto, el navegador web (como Chrome, Firefox o Edge) puede cargar y ejecutar código JavaScript dividido en archivos separados que se comunican entre sí usando estas instrucciones import y export.

5.2.¿Cómo sincronizar los módulos con el index.html?

Esto se hace agregando type="module" en la etiqueta <script> dentro del HTML. Es lo que le indica al navegador el script es un módulo.

EJEMPLO:

Al final del documento HTML, justo antes de la etiqueta de cierre del <body>, aplicamos la línea para sincronizar los archivos de export e import al HTML de la siguiente manera:

<body>
  <h1>¡Hola módulos!</h1>

  <!-- Usamos type="module" para permitir import/export -->
  <script type="module" src="./main.js"></script>
</body>Lenguaje del código: HTML, XML (xml)

main.js

import { saludar } from './saludo.js';

saludar('Manuel');Lenguaje del código: JavaScript (javascript)

saludo.js

export function saludar(nombre) {
  console.log(`Hola, ${nombre}!`);
}Lenguaje del código: JavaScript (javascript)

¿Qué sucede aquí?

  • El navegador interpreta que main.js es un módulo porque tiene type="module".
  • Entonces permite que ese archivo use import para traer la función saludar() desde otro archivo.
  • Si no usás type="module", el navegador lanza un error como: "Uncaught SyntaxError: Cannot use import statement outside a module"

5.3. Precauciones al sincronizar los módulos al index.html

5.3.1. Cuidado con errores de CORS y rutas

Cuando trabajas en local y abrís index.html directamente con doble clic (usando la ruta file:///C:/...), los navegadores bloquean los imports por razones de seguridad (CORS).

Error típico:

Access to script at 'file:///C:/.../saludo.js' from origin 'null' has been blocked by CORS policyLenguaje del código: JavaScript (javascript)

¿Qué causa este error?

  • El navegador impide que un módulo importado desde un archivo .js local acceda a otros archivos por razones de seguridad.
  • Esto no pasa cuando servís el archivo desde un servidor local (por ejemplo con Live Server o Vite).

5.3.2. ¿Cómo evitar el error? Usar un servidor local

OPCIÓN A: Live Server (más fácil)

  1. Instalá la extensión Live Server en Visual Studio Code.
  2. Hacé clic derecho sobre index.htmlOpen with Live Server.

💡 Esto abrirá tu HTML en http://localhost:5500/ (u otro puerto), lo que evita el error de CORS y permite cargar módulos sin problema.

OPCIÓN B: Vite (más profesional)

Vite es un entorno de desarrollo moderno muy rápido que usa módulos por defecto y recarga automática.

Pasos para usar Vite (una vez tengas Node.js instalado):

  1. Abrí tu terminal y ejecutá:
npm create vite@latest mi-proyectoLenguaje del código: CSS (css)
  1. Elegí «vanilla» como framework.
  2. Entrá a la carpeta:
cd mi-proyecto
npm install
npm run dev

Esto abrirá tu proyecto en http://localhost:5173/, con soporte completo para módulos y recarga automática.

5.3.3. Rutas relativas: muy importante

Cuando importas un archivo .js en un módulo, siempre tenemo que escribir la extensión .js y usar rutas relativas válidas.

// ✔️ Correcto
import { saludar } from './saludo.js';

// ❌ Incorrecto
import { saludar } from './saludo'; // Error: debe tener la extensión .jsLenguaje del código: JavaScript (javascript)

También debés prestar atención a la ubicación del archivo:

  • ./ → significa «en el mismo directorio».
  • ../ → significa «subir un nivel en la carpeta».

6. Buenas prácticas en el uso de módulos JavaScript

Dominar export e import te abre las puertas a un código más limpio y modular, pero hay prácticas y herramientas que elevan tu juego a un nivel superior.

  1. Planifica la estructura de tus módulos
  2. Coherencia en las exportaciones (y por qué las nombradas son a menudo preferibles)
  3. Renombra importaciones para claridad y evitar conflictos
  4. Entiende y usa las rutas de módulos correctamente
  5. Domina las herramientas de construcción (Bundlers)
  6. Aprovecha el «Tree Shaking»
  7. Utiliza Importaciones Dinámicas (import()) para Optimización

6.1. Planifica la estructura de tus módulos

Antes de empezar a codificar, dedica un momento a pensar en cómo vas a organizar tu proyecto.

  1. Cohesión y acoplamiento:
    • Intenta que tus módulos tengan alta cohesión (todo lo que está dentro de un módulo está muy relacionado entre sí) y bajo acoplamiento (un módulo depende lo menos posible de los detalles internos de otros módulos). Esto significa que un cambio en un módulo debería tener el menor impacto posible en otros.
  2. Separación de responsabilidades:
    • Identifica las responsabilidades claras de cada módulo. ¿Será un módulo de utilidades? ¿Un módulo para manejar la lógica de negocio de un usuario? ¿Un componente de UI? Una buena planificación evita módulos «cajón de sastre» donde metes de todo.
  3. Ejemplo:
    • En lugar de utils.js que tiene todo, podrías usar nombres más específicos sobre lo que estas aplicando como; mathUtils.js, stringUtils.js, dateUtils.js.

6.2. Coherencia en las exportaciones (y por qué las nombradas son a menudo preferibles)

Mantener la coherencia en cómo exportas desde tus archivos es vital para la legibilidad del equipo.

  1. Prioriza exportaciones nombradas:
    • En general, las exportaciones nombradas (export const foo, export function bar) son preferibles porque fomentan la claridad y son esenciales para el «tree shaking» (ver punto 6.6.). Al importarlas, siempre sabes exactamente qué estás obteniendo por su nombre explícito.
  2. Usa exportación por defecto con propósito:
    • Reserva la exportación por defecto (export default) para el elemento principal y único que un módulo expone. Por ejemplo, la clase App en App.js, o un componente principal en un framework. Si un archivo tiene más de una cosa importante, probablemente sea mejor usar exportaciones nombradas.
  3. Evita mezclar en exceso:
    • Aunque es posible (import Default, { Named } from './module.js';), el uso excesivo de combinaciones en un mismo archivo puede hacer que sea menos intuitivo ver qué se exporta. Si puedes, mantén tus módulos consistentes.

6.3. Renombra importaciones para claridad y evitar conflictos

Utiliza la palabra clave as inteligentemente al importar.

  1. Evitar conflictos de nombres:
    • Si importas dos funciones con el mismo nombre de módulos diferentes, as es tu salvador.
import { fetchUser } from './apiService.js';
import { fetchUser as getUserFromCache } from './cacheService.js'; // Renombrado

fetchUser();        // Llama a la API
getUserFromCache(); // Llama al cachéLenguaje del código: JavaScript (javascript)
  1. Mejorar la legibilidad:
    • A veces, el nombre de una exportación es demasiado genérico o largo. Renombrarla puede hacer tu código más claro localmente.

6.4. Entiende y usa las rutas de módulos correctamente

Las rutas en import son fundamentales y su comportamiento varía ligeramente según el entorno.

  1. Rutas relativas (./, ../): Son las más comunes y explícitas. Indican la ubicación del módulo a importar en relación con el módulo actual.
    • ./miArchivo.js: En el mismo directorio.
    • ../otroDirectorio/archivo.js: Un directorio arriba.
    • /raiz/modulo.js: Ruta absoluta desde la raíz del dominio (menos común en módulos de aplicación).
  2. Extensiones de archivo (.js, .mjs):
    • En el Navegador: Siempre debes incluir la extensión (.js, .mjs) al importar un módulo. El navegador no adivina.
    • En Node.js: Depende de tu configuración (.mjs o "type": "module" en package.json). Si usas type: "module", también debes incluir la extensión.
  3. «Bare Specifiers» (Nombres planos):import { debounce } from 'lodash';
    • Cuando ves esto, significa que el módulo viene de la carpeta node_modules. Ni el navegador ni Node.js (sin configuración especial) saben directamente cómo resolver 'lodash'. Aquí es donde entran los bundlers o el gestor de paquetes de Node.js.

6.5. Domina las herramientas de construcción (Bundlers)

Para cualquier aplicación JavaScript que vaya más allá de un pequeño script, usar un bundler (como Webpack, Rollup, o Vite) es casi obligatorio.

  • Resolución Automática de Módulos: Los bundlers pueden resolver nombres planos ('lodash') y a menudo te permiten omitir las extensiones de archivo (./miArchivo en lugar de ./miArchivo.js).
  • Transpilación (Babel): Te permiten escribir JavaScript moderno (ESM, sintaxis de punta) y automáticamente lo transforman a una versión compatible con navegadores más antiguos.
  • Optimización del Rendimiento: Minificación (reducir el tamaño del código), compresión, y la clave: Code Splitting (dividir tu aplicación en fragmentos más pequeños para una carga más rápida).

6.6. Aprovecha el «Tree Shaking»

El «Tree Shaking» (también conocido como «dead code elimination») es una optimización crucial que los bundlers pueden realizar.

  1. Cómo funciona:
    • Los bundlers analizan tu grafo de módulos. Si importas una librería grande pero solo usas una o dos funciones, el «tree shaking» eliminará automáticamente el código no utilizado de la librería del paquete final de tu aplicación.
  2. Beneficio:
    • Reduce drásticamente el tamaño final de tu JavaScript, lo que se traduce en tiempos de carga más rápidos para tus usuarios.
  3. Requisito:
    • Para que el «tree shaking» funcione eficazmente, las librerías deben usar ES Modules para sus exportaciones. Si una librería sigue usando CommonJS (require()), el «tree shaking» no funcionará con ella.

6.7. Utiliza Importaciones Dinámicas (import()) para Optimización

Las importaciones dinámicas son un patrón avanzado para la optimización del rendimiento.

  1. Carga bajo demanda (Lazy Loading):
    • Permiten cargar módulos solo cuando realmente se necesitan (por ejemplo, cuando un usuario hace clic en un botón, navega a una ruta específica, o un componente grande entra en la vista).
  2. Mejora del tiempo de carga inicial:
    • Al retrasar la carga de código no esencial, reduces el tamaño del bundle inicial que el navegador tiene que descargar y ejecutar, haciendo que tu aplicación sea más rápida al inicio.
  3. Sintaxis asíncrona:
    • Recuerda que import() devuelve una Promise, por lo que a menudo lo usarás con async/await.
// Ejemplo de un componente que solo se carga si el usuario lo solicita
document.getElementById('mostrarMapa').addEventListener('click', async () => {
  const { cargarMapa } = await import('./mapaUtils.js'); // El módulo 'mapaUtils.js' se descarga aquí
  cargarMapa('mi-div-mapa');
});Lenguaje del código: JavaScript (javascript)

7. Preguntas frecuentes y resumen sobre modulos en JS.

Los módulos export e import permiten dividir el código en archivos reutilizables. Con export se exponen funciones, objetos o variables, y con import se los puede usar en otro archivo, mejorando la organización y mantenibilidad.

Podés usar export delante de cualquier declaración: export const x = 5;, export function saludar() {...}, o export class Persona {...}. También podés hacer export { x, saludar } al final del archivo.

Usá import con llaves para importar elementos nombrados: import { x, saludar } from './archivo.js';. Para importación por defecto: import Usuario from './usuario.js';. Así reutilizás lo exportado desde otro módulo.

export default exporta un solo valor principal por módulo y se importa sin llaves. Los named exports permiten exportar múltiples elementos que se deben importar con su nombre exacto entre llaves. Ambos pueden coexistir en un mismo archivo.

Usá export default cuando el archivo tenga un único propósito, como una clase principal. Elegí named exports cuando quieras exportar múltiples utilidades o funciones relacionadas. Ambos estilos ayudan a estructurar el código.

Para importar todo el contenido nombrado de un módulo, usá import * as util from './utils.js';. Así agrupás todos los exports bajo un alias (en este caso util) y accedés a cada exportación como util.nombreFuncion().

Podés renombrar con as: al exportar export { funcionOriginal as nuevaFuncion }, o al importar import { funcionOriginal as util } from './modulo.js';. Esto es útil para evitar conflictos o mejorar legibilidad.

Los módulos permiten separar responsabilidades, reutilizar funciones y mantener el código limpio. Facilitan el mantenimiento, promueven buenas prácticas y evitan colisiones de nombres al aislar variables y funciones dentro de cada archivo.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *