Saltar al contenido
modulos.js · devschool

Módulos en JavaScript: import y export

Lección 24 de 38 · 4 min de lectura · Actualizado el

En esta lección
  1. Exportar
  2. Importar
  3. Exportación por defecto
  4. Módulos en el navegador
  5. Módulos en Node.js
  6. Cómo organizar un proyecto
  7. Empaquetadores

Cuando un programa crece, meterlo todo en un único archivo se vuelve inmanejable. Los módulos permiten dividir el código en archivos, cada uno con una responsabilidad, y usar en uno lo que exporta otro. En otros lenguajes se les llama librerías o bibliotecas.

Exportar

En un módulo, todo es privado por defecto. Para que otro archivo pueda usar algo, hay que exportarlo con export:

// matematicas.js
export const IVA = 0.21;

export function conIva(precio) {
  return redondear(precio * (1 + IVA));
}

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

// Sin export: solo se puede usar dentro de este archivo
function redondear(n) {
  return Math.round(n * 100) / 100;
}

Importar

// app.js
import { conIva, IVA } from "./matematicas.js";

console.log(conIva(100));   // 121
console.log(IVA);           // 0.21
  • Los nombres van entre llaves y deben coincidir con los exportados.
  • La ruta empieza por ./ (o ../) para indicar que es un archivo tuyo. Sin ella, JavaScript buscaría un paquete instalado con npm.
  • En el navegador la extensión .js es obligatoria.

Otras formas de importar:

import * as mates from "./matematicas.js";   // todo, dentro de un objeto
mates.sumar(2, 3);

import { sumar as suma } from "./matematicas.js";  // con otro nombre

La forma import * as mates tiene una ventaja: al leer mates.sumar(...), sabes de qué módulo viene la función. Con import { sumar }, tienes que ir al principio del archivo para saberlo. Elige una forma y úsala siempre en el proyecto.

Exportación por defecto

Cada módulo puede tener una exportación por defecto, que se importa sin llaves y con el nombre que quieras:

// Carrito.js
export default class Carrito {
  // ...
}
import Carrito from "./Carrito.js";

Es habitual cuando un archivo contiene una sola cosa principal, como una clase o un componente.

Módulos en el navegador

Para usar módulos en una página, el <script> principal necesita type="module":

<script type="module" src="js/app.js"></script>

Ese atributo no significa que app.js sea un módulo, sino que puede usar import. Solo hace falta en el script principal; los archivos que este importa se cargan solos.

Los scripts de tipo módulo:

  • Están siempre en modo estricto, sin escribir 'use strict'.
  • Se ejecutan cuando el HTML ya está cargado (como si llevaran defer).
  • Tienen su propio ámbito: sus variables no son globales, así que no chocan con las de otros scripts.

Hace falta un servidor

Si abres el HTML con doble clic (file:///...), los módulos no funcionan: el navegador lo bloquea por seguridad (política CORS). Tienes que servir la página desde un servidor web, aunque sea uno de pruebas en tu ordenador. Cualquiera de estas opciones vale:

  • La extensión Live Server de VS Code (clic derecho → Open with Live Server).
  • Con Node.js: npx serve en la carpeta del proyecto.
  • Con Python: python -m http.server 8000, y abres http://localhost:8000.
  • El servidor de desarrollo de tu herramienta (npm run dev en Astro o Vite).

Módulos en Node.js

Node.js también entiende import y export, pero necesita saber que tu archivo es un módulo. Dos formas:

  1. Usar la extensión .mjs: node app.mjs.
  2. Añadir "type": "module" al package.json del proyecto. Así todos los .js son módulos.
{
  "name": "mi-proyecto",
  "type": "module"
}

El sistema antiguo: require

En Node.js verás muchísimo código con otro sistema de módulos, CommonJS, anterior a los módulos estándar:

const express = require("express");
module.exports = { sumar };

Funciona, y lo seguirás encontrando en tutoriales y proyectos, pero para código nuevo usa import/export, que es el estándar y funciona igual en el navegador y en Node.js.

Cómo organizar un proyecto

Una estructura típica para una web pequeña:

js/
├── app.js            ← punto de entrada: conecta la página con la lógica
├── interfaz.js       ← funciones que leen y escriben en el DOM
├── logica/
│   ├── carrito.js    ← cálculos del carrito (sin nada del DOM)
│   └── validar.js    ← validaciones de formularios
└── api.js            ← llamadas al servidor con fetch

La lógica, separada del DOM, se puede probar directamente con Node.js. Es la idea de separar lógica e interfaz que viste en la lección de Node.js.

Empaquetadores

En proyectos profesionales, herramientas como Vite, esbuild o webpack (los bundlers) juntan todos tus módulos y los de npm en pocos archivos optimizados para el navegador. Astro, por ejemplo, usa Vite por debajo. Por eso ahí puedes importar sin extensión o importar paquetes de npm directamente.

Pon a prueba lo que has aprendido

[JavaScript] Abres con doble clic un HTML que carga un script type="module". ¿Qué pasa?

[JavaScript] ¿Cómo se importa una exportación por defecto?

¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.