Importación de módulos en Node.js
Cuando empiezas a escribir un proyecto de Node.js, uno de los primeros problemas que encuentras es: cómo importar módulos (module).
En Node.js, los módulos son archivos JavaScript reutilizables que se comunican entre sí mediante la importación (import) y la exportación (export).
El ecosistema de Node.js admite principalmente dos sistemas de módulos:CommonJSy ES Modules (ESM)。
| Sistema de módulos | Especificación | Extensión de archivo | Método de importación | Método de exportación |
|---|---|---|---|---|
| CommonJS | Usado por Node.js en sus inicios | .js |
require() |
module.exports / exports |
| ES Module (ESM) | Estándar ECMAScript | .mjso"type": "module" |
import |
export / export default |
Sistema de módulos CommonJS
CommonJS es el sistema de módulos más antiguo y más utilizado de Node.js. Adopta la carga síncrona, lo que significa que los módulos bloquean la ejecución del programa durante la carga hasta que esta se completa.
Importación y exportación
En CommonJS, usasrequire()función para importar módulos, y usasmodule.exportsoexportsobjeto para exportar módulos.
Método de exportación:
Código del archivo math.js:
function add(a, b) {
return a + b;
}
module.exports = { add };
// O bien: exports.add = add;
Método de importación:
Ejemplo
const math = require('./math.js');
console.log(math.add(2, 3)); // 5
Para que un módulo permita que el exterior acceda a su contenido, debe usar module.exports o exports para exportar:
Ejemplo
const name = 'Alice';
const age = 30;
// Método 1: usar module.exports para exportar un objeto o valor único
module.exports = {
name: name,
age: age,
sayHello: () => {
console.log(`Hello, my name is ${name}.`);
}
};
// Método 2: usar exports para exportar múltiples variables con nombre
// exports es una referencia a module.exports
exports.name = name;
exports.age = age;
exports.sayHello = () => {
console.log(`Hello, my name is ${name}.`);
};
Método de importación:
Ejemplo
const user = require('./user.js');
console.log(user.name); // Salida: Alice
user.sayHello(); // Salida: Hello, my name is Alice.
// También se puede desestructurar directamente
const { name, age } = require('./user.js');
console.log(name); // Salida: Alice
Características de CommonJS:
- **Carga síncrona**: adecuada para entornos de servidor, porque los módulos suelen estar en el sistema de archivos local y la carga es rápida.
- **Carga en tiempo de ejecución**:
require()Se puede invocar en cualquier parte del código, lo que permite cargar módulos dinámicamente según las condiciones. - **Mecanismo de caché**:
require()Los módulos cargados se almacenan en caché; en la segunda importación se leen directamente de la caché, evitando cargas repetidas.
Especificación ES Module (ESM)
ESM es el estándar oficial de módulos de JavaScript. Adopta la carga asíncrona y es la opción preferida para navegadores y aplicaciones modernas de Node.js.
En ESM, usasimportsentencia para importar módulos, y usasexportsentencia para exportar módulos.
Habilitar ESM:Para usar ESM en Node.js, necesitas agregar en el archivo package.json"type": "module", o cambiar la extensión del archivo a.mjs。
// package.json
{
"type": "module"
}
Exportar módulo:
Ejemplo
export function add(a, b) {
return a + b;
}
export default function multiply(a, b) {
return a * b;
}
Importar módulo:
Ejemplo
import multiply, { add } from './math.mjs';
console.log(add(2, 3)); // 5
console.log(multiply(2, 3)); // 6
Forma de habilitación:
Usa la extensión de archivo.mjs
o agrega en package.json:
{ "type": "module" }
ESM admite dos formas de exportación: exportaciones con nombre (Named Exports) y exportación por defecto (Default Export).
Ejemplo
// Exportación con nombre
export const name = 'Bob';
export const age = 25;
// Exportación por defecto
const sayHello = () => {
console.log(`Hello, my name is ${name}.`);
};
export default sayHello;
Método de importación:
Ejemplo
// Importar exportación con nombre
import { name, age } from './user.mjs';
console.log(name); // Salida: Bob
// Importar exportación por defecto
import sayHello from './user.mjs';
sayHello(); // Salida: Hello, my name is Bob.
// Importar tanto la exportación con nombre como la por defecto
import sayHello, { name } from './user.mjs';
console.log(name);
sayHello();
// Importar todas las exportaciones con nombre y usarlas como propiedades de un objeto
import * as user from './user.mjs';
console.log(user.name);
user.default(); // La exportación por defecto estará en la propiedad default
Características de ESM:
- **Carga asíncrona**: por defecto es asíncrona, no bloquea el hilo principal y es más adecuada para entornos de navegador, aunque en Node.js suele comportarse como una carga síncrona.
- **Análisis estático**:
importyexportLas sentencias pueden determinar las dependencias del módulo antes de la ejecución del código, lo que permite a herramientas (como Webpack, Vite) realizar mejores optimizaciones (comoTree Shaking)。 - **Modo estricto**: los módulos ESM se ejecutan en modo estricto por defecto.
Diferencias entre CommonJS y ESM
| Aspecto | CommonJS | ESM |
|---|---|---|
| Sintaxis | require / module.exports |
import / export |
| Mecanismo de carga | Carga síncrona en tiempo de ejecución | Carga estática en tiempo de compilación |
| Soporte por defecto | Compatible con Node.js por defecto | Necesita.mjso"type": "module" |
| Escenarios adecuados | Scripts de backend, proyectos antiguos | Proyectos modernos de frontend y backend, Tree-shaking |
| ¿Se puede mezclar? | No se pueden mezclar directamente (requiere configuración adicional) | No se pueden mezclar directamente (requiere configuración adicional) |
Uso mixto
Node.js admite la coexistencia de dos sistemas de módulos en versiones recientes. Puedes usar CommonJS y ESM a la vez en el mismo proyecto, pero debes tener en cuenta los siguientes puntos:
- En ESM no se puede usar directamente
require()ymodule.exports。 - En CommonJS no se puede usar directamente
importyexport。 -
Si quieres importar módulos CommonJS en ESM, puedes usar directamente
importsentencia; ESM lo tratará como una exportación por defecto.// commonjs_module.js module.exports = { data: 'hello' }; // esm_module.mjs import commonModule from './commonjs_module.js'; console.log(commonModule.data); // 输出: hello -
Si quieres importar módulos ESM en CommonJS, necesitas usar la función dinámica
import()función.// esm_module.mjs export const name = 'Bob'; // commonjs_module.js async function loadESM() { const { name } = await import('./esm_module.mjs'); console.log(name); } loadESM();
Recomendaciones de mejores prácticas
Para proyectos nuevos,se recomienda encarecidamente usar ES Modules (ESM). No solo es el estándar oficial de JavaScript, sino que también tiene mejor compatibilidad con las herramientas modernas de frontend (como Vite, Next.js), y permite aprovechar al máximo técnicas de optimización como Tree Shaking, reduciendo el tamaño del código empaquetado.
Si estás manteniendo un proyecto CommonJS antiguo y no necesitas las características de ESM, puedes seguir usando CommonJS. Pero si necesitas incorporar nuevas dependencias o aprovechar las nuevas características de ESM, considera migrar gradualmente o usar el modo híbrido como transición.
Otras extensiones