Ficheros y sistema de módulos en Node.js
En esta clase damos el primer paso real trabajando con Node.js: crear archivos, ejecutarlos desde la terminal y entender cómo funciona su sistema de módulos, que es uno de los puntos donde más confusión suele haber al venir del frontend.
Creando el primer fichero en Node.js
Partimos de una carpeta vacía. No hay configuración, no hay magia. Creamos nuestro primer archivo: index.js.
Dentro escribimos el clásico Hello World y lo ejecutamos desde la terminal:
// index.js
console.log('¡Hola mundo desde Node.js!')
Ejecutamos en la terminal:
node index.js
Si vemos el mensaje por consola, ya sabemos dos cosas importantes:
- Node.js está correctamente instalado.
- Estamos usando la versión adecuada.
Dividir el código en ficheros
Igual que en frontend, no queremos tener todo en un solo archivo. Vamos a separar la lógica. Por ejemplo, vamos a crear un archivo para funciones matemáticas.
1. Creamos math.js
// math.js
export function sumar(a, b) {
return a + b
}
export function restar(a, b) {
return a - b
}
2. Intentamos usarlo en index.js
// index.js
import { sumar } from './math'
console.log(sumar(5, 5))
El error más común al importar módulos
Aunque el código parece correcto, Node.js lanzará un error diciendo que no encuentra el módulo si olvidas la extensión. ¿El motivo?
En Node.js, la extensión del fichero es obligatoria.
Nota importante: En el frontend, gracias a herramientas como Vite o Webpack, la extensión suele ser opcional porque el empaquetador la busca por ti. En Node.js, en tiempo de ejecución (runtime), no lo es.
Si el archivo se llama math.js, tienes que importar explícitamente ./math.js. Node.js no pierde tiempo intentando “adivinar” si buscas un .js, .json o una carpeta; busca exactamente lo que le pides.
Runtime vs Build time
Esta diferencia es fundamental para entender por qué Node.js es más estricto:
| Concepto | Entorno | Comportamiento |
|---|---|---|
| Runtime | Node.js | El código se ejecuta directamente. Debe ser explícito. |
| Build time | Frontend | Un “empaquetador” procesa el código antes de enviarlo al navegador. |
¿Y la advertencia?
Una vez solucionado el problema de añadir la extensión, Node.js nos mostrará una advertencia:
(node:12345) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
Esta advertencia nos indica que debemos configurar nuestro proyecto para usar ES Modules.
Según la versión que estés usando es posible que sea un error y el programa no se ejecute o sea simplemente una advertencia (aunque te dirá que puede haber problemas de rendimiento). ¿Por qué pasa esto?
Porque Node.js no usa ES Modules por defecto, sino que usa CommonJS.
El pasado: CommonJS
Antes de que existiera un estándar oficial de módulos en JavaScript (ES Modules), Node.js creó su propio sistema llamado CommonJS. Todavía lo verás en muchos proyectos antiguos o librerías de npm.
Ejemplo en CommonJS:
// math.js (Estilo antiguo)
function sumar(a, b) {
return a + b
}
module.exports = { sumar }
// index.js (Estilo antiguo)
const { sumar } = require('./math') // Aquí la extensión solía ser opcional
console.log(sumar(5, 5))
¿Por qué no se recomienda hoy en día? “CommonJS es un sistema síncrono y pensado originalmente para servidores, lo que lo hace incompatible con el estándar actual de la web. ES Modules es el estándar oficial de JavaScript, permite el ‘tree-shaking’ (eliminar código que no usas) y es compatible tanto con el navegador como con Node.js moderno.”
El presente: ES Modules
Es el estándar que usamos hoy en día (import / export). Para que Node.js sepa que queremos usarlo, debemos configurar nuestro proyecto.
Configurando el tipo de módulo
Debemos crear un archivo package.json en la raíz de nuestro proyecto:
// package.json
{
"type": "module"
}
Con esta propiedad "type": "module", Node.js:
- Deja de mostrar advertencias.
- Activa el soporte completo para
importyexport. - Nos permite usar el estándar moderno de la industria.
Antes de acabar…
Entender el sistema de módulos es vital para no frustrarse con errores de “módulo no encontrado” o advertencias extrañas en la terminal.
- ✅ Ejecutamos con
node nombre-archivo.js. - ✅ La extensión
.jses obligatoria en los imports de ES Modules. - ✅ Usamos
"type": "module"en elpackage.jsonpara trabajar con la sintaxis moderna.
En la siguiente clase ya empezamos a construir cosas más interesantes sobre esta base sólida.