Backend
Actualizado el 6 de noviembre de 2026
Node.js
Node.js 22/24 LTS: versiones con fnm, ejecutar scripts, ESM, APIs nativas, test runner, servidor HTTP, depuración y dependencias con pnpm.
- #nodejs
- #javascript
- #pnpm
- #backend
Versiones con fnm
| Acción | Comando |
|---|---|
| Instalar la última LTS | |
| Instalar una versión concreta | |
| Usar una versión en la terminal actual | |
| Definir la versión por defecto | |
| Listar versiones instaladas | |
| Fijar la versión del proyecto | |
Cambiar de versión al entrar a la carpeta (en ~/.bashrc) |
Equivalentes con nvm
| Acción | Comando |
|---|---|
| Instalar la última LTS | |
Usar la versión de .nvmrc | |
| Definir la versión por defecto | |
| Listar versiones instaladas |
Ejecutar código
| Acción | Comando |
|---|---|
| Ejecutar un archivo | |
| Reiniciar al guardar cambios | |
Cargar variables desde .env | |
Combinar watch y .env | |
Ejecutar un script de package.json sin pnpm | |
| Evaluar una expresión rápida | |
| Abrir el REPL interactivo | |
| Ver la versión instalada |
En el REPL, .help muestra los comandos, .exit (o Ctrl + d) sale y _ guarda el último resultado.
Módulos: ESM vs CommonJS
| Concepto | Descripción |
|---|---|
"type": "module" | En package.json, hace que los .js sean ESM (import/export) |
.mjs / .cjs | Fuerzan ESM o CommonJS sin importar el "type" |
import x from './x.js' | En ESM la extensión del archivo es obligatoria |
require('./x') | Sintaxis CommonJS; no existe en ESM |
import.meta.dirname | Carpeta del módulo actual (sustituye a __dirname en ESM) |
import.meta.filename | Ruta absoluta del archivo actual (sustituye a __filename) |
Top-level await | Permitido en ESM, fuera de funciones async |
javascript
// ESM: named exports, JSON import with attributes, top-level await
import { readFile } from 'node:fs/promises';
import config from './config.json' with { type: 'json' };
export const name = config.name;
const data = await readFile(new URL('./data.txt', import.meta.url), 'utf8');APIs nativas útiles
javascript
import { readFile, writeFile, mkdir, readdir } from 'node:fs/promises';
import { join, extname, basename } from 'node:path';
const dir = join(import.meta.dirname, 'output');
await mkdir(dir, { recursive: true });
const files = await readdir(import.meta.dirname);
const jsFiles = files.filter((f) => extname(f) === '.js');
await writeFile(join(dir, 'report.json'), JSON.stringify({ jsFiles }, null, 2));
const text = await readFile(join(dir, 'report.json'), 'utf8');
console.log(basename(dir), text.length);| API | Para qué sirve |
|---|---|
process.env.PORT | Leer variables de entorno (siempre son strings) |
process.argv.slice(2) | Argumentos pasados al script |
process.exit(1) | Terminar con código de error |
process.cwd() | Carpeta desde donde se ejecutó Node |
fileURLToPath(import.meta.url) | Convertir una URL file:// a ruta (de node:url) |
util.parseArgs() | Parsear flags de CLI sin librerías (de node:util) |
fetch nativo
javascript
const res = await fetch('https://api.example.com/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Ana', createdAt: new Date().toISOString() }),
signal: AbortSignal.timeout(5000), // abort after 5 s
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const user = await res.json();Test runner nativo
| Acción | Comando |
|---|---|
Ejecutar todos los tests (*.test.js, test/…) | |
| Ejecutar un archivo concreto | |
| Re-ejecutar al guardar | |
| Filtrar tests por nombre |
javascript
// src/sum.test.js
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { sum } from './sum.js';
describe('sum', () => {
it('adds two numbers', () => {
assert.equal(sum(2, 3), 5);
});
it('rejects non-numbers', () => {
assert.throws(() => sum('a', 1), TypeError);
});
});Servidor HTTP mínimo
javascript
// server.js — run with: node --watch --env-file=.env server.js
import { createServer } from 'node:http';
const port = Number(process.env.PORT ?? 3000);
const server = createServer((req, res) => {
if (req.method === 'GET' && req.url === '/health') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ status: 'ok', time: new Date().toISOString() }));
return;
}
res.writeHead(404, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Not found' }));
});
server.listen(port, () => console.log(`Listening on http://localhost:${port}`));Depuración
| Acción | Comando |
|---|---|
| Activar el inspector (puerto 9229) | |
| Pausar en la primera línea | |
| Inspector accesible desde otra máquina o contenedor | |
| Depurar los tests | |
| Mostrar dónde se lanzó una excepción no capturada |
Abre chrome://inspect en Chrome o usa la configuración “Attach” de VS Code. Dentro del código, debugger; detiene la ejecución cuando el inspector está activo.
Dependencias con pnpm
| Acción | Comando |
|---|---|
Crear package.json | |
| Instalar todo lo del lockfile | |
| Instalar en CI respetando el lockfile | |
| Añadir una dependencia | |
| Añadir una dependencia de desarrollo | |
| Quitar una dependencia | |
| Actualizar dentro de los rangos permitidos | |
| Actualizar a la última versión (ignora rangos) | |
| Ver dependencias desactualizadas | |
| Saber por qué está instalado un paquete |
Ejecutar paquetes y scripts con pnpm
| Acción | Comando |
|---|---|
Ejecutar un script de package.json | |
| Atajo para scripts (si no choca con un comando de pnpm) | |
| Pasar argumentos al script | |
| Ejecutar un binario instalado en el proyecto | |
| Ejecutar un paquete sin instalarlo | |
| Listar los scripts disponibles |
json
{
"type": "module",
"engines": { "node": ">=22" },
"scripts": {
"dev": "node --watch --env-file=.env src/server.js",
"start": "node src/server.js",
"test": "node --test",
"lint": "eslint ."
}
}