Server Runtime

Conceptos básicos de Node.js

Node.js ejecuta JavaScript fuera del navegador, en el servidor. Su I/O no bloqueante y su enorme ecosistema lo convierten en una opción natural para APIs, herramientas y aplicaciones full-stack.

beginner15 min readUpdated 15 sept 2026
server.js
js
// server.js
import { createServer } from "node:http";

const server = createServer((req, res) => {
  if (req.url === "/health") {
    res.writeHead(200, { "Content-Type": "application/json" });
    res.end(JSON.stringify({ status: "ok" }));
    return;
  }
  res.writeHead(404).end("Not found");
});

server.listen(3000, () => {
  console.log("http://localhost:3000");
});
Primer lanzamiento
2009, por Ryan Dahl
Motor
V8
Modelo
No bloqueante, basado en eventos
Módulos
ESM y CommonJS
Paquetes
registro de npm
Ideal para
APIs, herramientas, apps en tiempo real

Por que importa

Por qué Node.js es importante

JavaScript en el servidor

Usa el mismo lenguaje en ambos lados de la conexión, lo que simplifica los equipos, el tooling y el intercambio de código.

I/O no bloqueante

El event loop sigue gestionando solicitudes mientras espera archivos, redes y bases de datos, manteniendo así un alto rendimiento.

Un ecosistema masivo

npm proporciona paquetes para casi cualquier tarea, y frameworks como Express y Fastify hacen que la creación de APIs sea rápida.

La imagen completa

Las tres ideas detrás de Node.js

Un motor de JavaScript, un event loop no bloqueante y una librería estándar para archivos, redes y procesos.

El runtime

Ejecutar

V8 más las APIs de Node para archivos, redes, procesos y temporizadores.

El event loop

Programar

Un solo hilo, una cola de callbacks y llamadas al sistema no bloqueantes.

El ecosistema

Extender

El registro de npm suministra frameworks, librerías y herramientas de línea de comandos.

Node.js de un vistazo

El núcleo de Node.js

Servidor HTTP

Construye una API con el módulo http integrado o con un framework.

Sistema de archivos

Lee y escribe archivos con la API async fs.

process y env

Lee argumentos, variables de entorno y códigos de salida.

Eventos y streams

Gestiona datos en fragmentos y responde a eventos a medida que ocurren.

Módulos

Organiza el código con import y export de ESM.

APIs y herramientas

Construye APIs REST, servidores GraphQL, CLIs y workers en segundo plano.

Una breve historia

JavaScript escapa del navegador

  1. 2009

    Lanzamiento de Node.js

    Ryan Dahl ejecuta JavaScript en el servidor con un modelo basado en eventos.

    09
  2. 2011

    npm y Express

    Un gestor de paquetes y un framework web aceleran su adopción.

    11
  3. 2015

    Soporte a largo plazo

    Los lanzamientos LTS y una fundación aportan estabilidad al uso en producción.

    15
  4. 2017

    async/await

    El código de servidor asíncrono se vuelve mucho más fácil de leer.

    17
  5. Hoy

    En todas partes

    El runtime por defecto para herramientas de build, APIs, funciones serverless y CLIs.

    Hoy

La guia completa

Conceptos básicos de Node.js: Todo lo que necesitas saber

Por qué Node.js es importante

Node.js es un runtime que ejecuta JavaScript fuera del navegador. Lanzado en 2009, tomó el motor V8 de Chrome y lo combinó con APIs para archivos, redes y procesos, permitiendo que los desarrolladores utilicen un solo lenguaje en todo el stack.

Su característica definitoria es el I/O no bloqueante y orientado a eventos. En lugar de reservar un hilo por solicitud y esperar mientras el disco o la red responden, Node delega la operación lenta y continúa con otras tareas. Cuando la operación finaliza, se ejecuta un callback. Este modelo lo hace eficiente para APIs, aplicaciones en tiempo real y herramientas, y es el mismo event loop que ya conoces de JavaScript en el navegador.

Ejecutando JavaScript en el servidor

Node te proporciona un process global, un sistema de módulos y una librería estándar. Un servidor HTTP mínimo no requiere dependencias.

// server.js
import { createServer } from "node:http";

const server = createServer((req, res) => {
  if (req.url === "/health") {
    res.writeHead(200, { "Content-Type": "application/json" });
    res.end(JSON.stringify({ status: "ok" }));
    return;
  }
  res.writeHead(404).end("Not found");
});

server.listen(process.env.PORT ?? 3000);

Las importaciones integradas con el prefijo node: dejan claro qué módulos provienen del propio Node. Este servidor gestiona las solicitudes a medida que llegan y nunca bloquea la E/S.

Módulos

El Node moderno utiliza ES modules, la misma sintaxis de import y export que el navegador.

// math.js
export function add(a, b) {
  return a + b;
}

// app.js
import { add } from "./math.js";

Configura "type": "module" en package.json para tratar los archivos .js como ES modules. Node también sigue dando soporte a CommonJS (require y module.exports), con el que te encontrarás en código antiguo y en muchos paquetes. Los proyectos nuevos deberían utilizar ES modules.

El sistema de archivos

La API del sistema de archivos de Node tiene variantes asíncronas y síncronas. Utiliza la API asíncrona en los servidores.

// files.js
import { readFile, writeFile } from "node:fs/promises";
import path from "node:path";

const file = path.join(import.meta.dirname, "data.json");
const data = JSON.parse(await readFile(file, "utf8"));

await writeFile(file, JSON.stringify({ ...data, updated: Date.now() }, null, 2));

El módulo node:path gestiona la unión de rutas entre plataformas, y import.meta.dirname proporciona el directorio del archivo actual. Existen funciones síncronas como readFileSync que son adecuadas en scripts y código de inicio, pero nunca deben usarse dentro de un manejador de solicitudes.

Entorno y configuración

La configuración debe residir en variables de entorno, no en el código.

// env.js
const config = {
  port: Number(process.env.PORT ?? 3000),
  databaseUrl: process.env.DATABASE_URL,
  nodeEnv: process.env.NODE_ENV ?? "development",
};

Esto evita que los secretos terminen en el repositorio y permite que la misma build se ejecute en desarrollo, staging y producción. En desarrollo, carga los valores locales desde un archivo .env utilizando una herramienta como dotenv o la funcionalidad integrada --env-file de Node.js, y nunca subas ese archivo al repositorio.

Creación de APIs

La mayoría de las aplicaciones de Node.js utilizan un framework para gestionar el routing, el parsing y el middleware. Express es el más utilizado; Fastify es más rápido y está orientado a esquemas.

// api.js
import express from "express";

const app = express();
app.use(express.json());

app.get("/api/users", async (req, res, next) => {
  try {
    const users = await db.users.findMany();
    res.json(users);
  } catch (error) {
    next(error);
  }
});

app.post("/api/users", async (req, res, next) => {
  try {
    const user = await db.users.create(req.body);
    res.status(201).json(user);
  } catch (error) {
    next(error);
  }
});

app.use((error, req, res, next) => {
  console.error(error);
  res.status(500).json({ message: "Something went wrong" });
});

app.listen(config.port);

Los manejadores de rutas (route handlers) son funciones async, los errores se redirigen al middleware y un manejador de errores final convierte las excepciones en respuestas. Devuelve códigos de estado y encabezados significativos, y consulta Seguridad Web para validar la entrada y proteger las sesiones.

Streams, buffers y eventos

Node maneja los datos como streams para que las cargas pesadas no tengan que caber enteramente en la memoria.

// stream.js
import { createReadStream } from "node:fs";
import { createServer } from "node:http";

createServer((req, res) => {
  createReadStream("movie.mp4").pipe(res);
}).listen(3000);

Un buffer son datos binarios en bruto, y un event emitter permite que los objetos publiquen eventos a los que otros se suscriben. Los streams y los eventos son la maquinaria de bajo nivel detrás de gran parte de la librería estándar de Node; entenderlos permite comprender cómo funcionan los archivos, los sockets y HTTP internamente.

Errores y señales de proceso

Los errores no controlados pueden provocar la caída de un proceso de Node.js, por lo que debes gestionarlos de manera deliberada.

// signals.js
process.on("SIGTERM", () => {
  server.close(() => process.exit(0));
});

process.on("unhandledRejection", (reason) => {
  console.error("Unhandled rejection", reason);
});

SIGTERM es enviada por la mayoría de las plataformas cuando un contenedor o proceso debe detenerse; gestionarla te permite finalizar las solicitudes en curso antes de salir. Los manejadores globales son una red de seguridad para el registro de logs, no un sustituto de la gestión de errores en el lugar donde ocurren.

Mejores prácticas

  • Utiliza APIs async en los request handlers y nunca bloquees el event loop.
  • Mantén la configuración en variables de entorno.
  • Valida y sanitiza todas las entradas en el servidor.
  • Utiliza ES modules y el prefijo node: para los built-ins.
  • Centraliza el manejo de errores en middleware.
  • Transmite archivos grandes mediante streams en lugar de leerlos en memoria.
  • Gestiona SIGTERM para un apagado controlado (graceful shutdown) y expón un endpoint de salud (health endpoint).

Errores comunes

  • Usar readFileSync dentro de un request handler y bloquear el servidor.
  • Realizar tareas pesadas de CPU en el hilo principal.
  • Hacer commit de archivos .env o escribir secretos directamente en el código.
  • Confiar en la entrada del cliente sin validarla.
  • Ignorar las promesas rechazadas no gestionadas (unhandled promise rejections).
  • Leer archivos grandes completamente en memoria en lugar de usar streaming.

Próximos pasos

Node.js completa el panorama full-stack. Gestiona las dependencias con npm, comprende el protocolo HTTP que utiliza tu servidor, asegúralo con Web Security y empaquétalo con Docker. Después, construye una API pequeña con dos rutas, una llamada a la base de datos y un manejador de errores, y despliégala.

Lectura de archivos

Usa la API async para que el event loop permanezca libre. Las llamadas bloqueantes detienen todas las demás solicitudes mientras esperan.

Preferir
import { readFile } from "node:fs/promises";

const data = await readFile("config.json", "utf8");
const config = JSON.parse(data);
Evitar
import { readFileSync } from "node:fs";

// blocks the whole server
// while the disk responds
const data = readFileSync("config.json", "utf8");

Configuración

Lee secretos y valores específicos del entorno desde variables de entorno para que la misma imagen funcione en cualquier entorno.

Preferir
const port = process.env.PORT ?? 3000;
const dbUrl = process.env.DATABASE_URL;
Evitar
const port = 3000;
const dbUrl = "postgres://localhost/prod";
// committed credentials

Preguntas frecuentes

Preguntas frecuentes

Keep learning

Related topics from the roadmap.

$ comienza a aprender

Listo para aprender Node.js Basics?

Nuestro tutorial interactivo te guia a traves de Node.js Basics paso a paso — con quizzes y codigo real que puedes ejecutar en el navegador.