Node.js

Node.js

¿Qué es Node.js?

Node.js es un entorno de ejecución de JavaScript que se ejecuta fuera del navegador, construido sobre el motor V8 de Google Chrome.
Permite usar JavaScript en el lado del servidor para crear aplicaciones escalables y rápidas.

Diferencias clave:

¿Para qué se usa?

Node.js se utiliza principalmente para aplicaciones que necesitan alta concurrencia y operaciones en tiempo real, como:

Mejor contexto:
cuando hay muchas operaciones de entrada/salida (I/O) y se busca eficiencia sin bloquear procesos.

¿Qué puedo construir con Node.js?

Con Node.js se pueden crear distintos tipos de aplicaciones, por ejemplo:

¿Cuándo es más conveniente usarlo?

Conviene usar Node.js cuando:

No es la mejor opción cuando:

Buenas prácticas recomendadas

Resumen rápido

✅ Fortalezas principales:

⚠️ Debilidades principales:

🛠️ Cuándo usarlo:

🚫 Cuándo evitarlo:


Temas


Conceptos relacionados

¿Qué es un ORM?

Object Relational Mapper: herramienta que permite interactuar con bases de datos usando objetos y métodos en lugar de SQL directo (ejemplo: Sequelize, TypeORM, Prisma).

¿Qué es una API?

Application Programming Interface: conjunto de reglas que permite que dos aplicaciones se comuniquen. En el contexto web suele ser un servicio que expone datos y funcionalidades.

¿Qué es el patrón REST?

Estilo de arquitectura para construir APIs que utiliza HTTP y operaciones como GET, POST, PUT, DELETE siguiendo convenciones en las rutas y respuestas.

¿Qué es Serverless?

Modelo en el que no administras servidores, sino que el proveedor (ej: AWS Lambda, Firebase Functions) ejecuta funciones bajo demanda y escala automáticamente.

¿Qué es arquitectura de Microservicios?

Es un estilo donde una aplicación grande se divide en pequeños servicios independientes, cada uno con su propia lógica y base de datos, que se comunican entre sí (generalmente vía APIs).


Lenguaje y fundamentos

Módulos y dependencias

Servidor y red

Bases de datos

Pruebas y calidad

🔼 temas


Herramientas recomendadas

1. Frameworks para aplicaciones web

2. Frameworks para tiempo real

3. Bases de datos y ORM/ODM

4. Testing y calidad

5. Utilidades y herramientas de desarrollo

6. Seguridad y autenticación

🔼 temas


Snippets rápidos

Servidor básico con Express

const express = require("express");
const app = express();
const PORT = 3000;

app.get("/", (req, res) => {
  res.send("Hola Mundo!");
});

app.listen(PORT, () => {
  console.log(`Servidor corriendo en http://localhost:${PORT}`);
});

Lectura y escritura de archivos

const fs = require("fs");

// Leer archivo
fs.readFile("archivo.txt", "utf8", (err, data) => {
  if (err) throw err;
  console.log(data);
});

// Escribir archivo
fs.writeFile("archivo.txt", "Contenido nuevo", (err) => {
  if (err) throw err;
  console.log("Archivo guardado");
});

Conexión a MongoDB con Mongoose

const mongoose = require("mongoose");

mongoose
  .connect("mongodb://localhost:27017/miDB", {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  })
  .then(() => console.log("Conectado a MongoDB"))
  .catch((err) => console.error("Error al conectar", err));

🔼 temas


Comandos

Control de versiones de Node

nvm                           # controlador de version de Node.js
nvm install <v nroVersion>    # instala la version elegida
nvm list                      # muestra la versiones instaladas
nvm use <v nroVersion>        # activa la version elegida
nvm uninstall <v nroVersion>  # instala la version elegida
nvm alias default node        # usa la ultima version instalada

Comandos Básicos

node nomArch            # Ejecuta archivos JavaScript con Node.js.
node -V                 # Muestra la versión actual de Node.js instalada.
node --inspect nomArch  # Inicia la depuración de un archivo JavaScript.
node .<comando>         # es la consola en Node.js
comandos                # [ break, clear, editor, exit, help, load, sav ]

Comandos de NPM (Node Package Manager)

npm init                            # Crea un nuevo archivo package.json interactivo en el directorio actual.
npm i/install                       # Instala todas las dependencias listadas en package.json.
npm i/install <package>             # Instala un paquete específico y lo añade a package.json como DEPENDENCIA.
npm i/install <package> --save-dev  # Instala un paquete específico y lo añade a package.json como dev-dependencies.
npm un/uninstall <package>          # Desinstala un paquete específico y lo elimina de package.json.
npm run <script>                    # Ejecuta un script definido en la sección scripts de package.json.
npm ls/list                         # Muestra una lista de todos los paquetes instalados y sus dependencias.
npm outdate                         # Muestra una lista de paquetes desactualizado.
npm update <package>                # Actualiza todos los paquetes a sus versiones más recientes según las restricciones en package.json.
                                    # Se tiene que actualizar manualmente las DEPENDENCIA en el package.json
npm cache clean --forc              # Limpia la caché de npm.

Paquete server

npm -i --g serve   # Es como live-server para Node.js

Comandos de NPX

npx <command>   # Ejecuta comandos npm sin necesidad de instalarlos globalmente.

Comandos de Control de Versiones

nvm install 14.17.0   # instalar la versión n°
nvm use 14.17.0       # usar la versión n°

🔼 temas


Conceptos Claves

🟢 Básico

1. Explica qué es Node.js y describe cómo maneja las operaciones de entrada y salida de manera no bloqueante.

Node.js es un entorno de ejecución de JavaScript del lado del servidor construido sobre el motor V8 de Google Chrome.
Se caracteriza por ser event-driven (basado en eventos) y non-blocking (no bloqueante).
Esto significa que las operaciones de entrada/salida (E/S) como lecturas de archivos, consultas a bases de datos o peticiones HTTP no detienen la ejecución del programa.
En lugar de esperar la finalización de una tarea, Node.js utiliza callbacks, promesas o async/await para manejar los resultados cuando están listos.

Ejemplo:

const fs = require("fs");
fs.readFile("archivo.txt", "utf8", (err, data) => {
  if (err) throw err;
  console.log(data);
});
console.log("Leyendo archivo...");

Salida:

Leyendo archivo...
<contenido del archivo>

2. ¿Cuál es la diferencia entre require y import en Node.js? ¿Cuándo utilizarías cada uno?

require

const express = require("express");

import

import express from "express";

Cuándo usar cada uno:

3. Describe la función del Event Loop en Node.js y cómo se relaciona con la concurrencia.

El Event Loop es el núcleo de Node.js encargado de gestionar tareas asincrónicas.
Permite que Node.js maneje múltiples operaciones concurrentes sin usar múltiples hilos directamente.

Flujo básico:

  1. Node.js ejecuta código en el stack principal.
  2. Las tareas asincrónicas se envían a la cola de eventos.
  3. El Event Loop revisa la cola y ejecuta los callbacks cuando estén listos.

Esto permite que Node.js atienda miles de conexiones simultáneamente con un solo hilo principal.

4. ¿Qué diferencia existe entre procesos e hilos en Node.js y cómo los gestiona internamente?

En Node.js:

Para tareas paralelas:

5. Menciona y explica al menos tres módulos nativos de Node.js.


🟡 Intermedio

6. Describe el patrón de diseño EventEmitter.

EventEmitter es un patrón en el que un objeto emite eventos y otros objetos se suscriben a esos eventos.

Ejemplo:

const EventEmitter = require("events");
const emisor = new EventEmitter();

// Suscriptor
emisor.on("saludo", (nombre) => console.log(`Hola ${nombre}`));

// Emisor
emisor.emit("saludo", "Fernando");

7. Diferencia entre código sincrónico y asincrónico.

Ejemplo asincrónico: Consulta a base de datos

db.query("SELECT * FROM usuarios", (err, data) => {
  console.log("Datos obtenidos");
});
console.log("Consulta enviada");

Salida:

Consulta enviada
Datos obtenidos

8. ¿Qué son los streams en Node.js y en qué casos se recomienda utilizarlos?

Los streams permiten procesar datos de manera fragmentada, sin cargar todo en memoria.
Se usan para manejar grandes cantidades de datos, como archivos o videos.

Tipos de streams:

Ejemplo: Leer archivo línea por línea

const fs = require("fs");
const stream = fs.createReadStream("archivo.txt", "utf8");
stream.on("data", (chunk) => console.log(chunk));

9. Flujo de creación de una API REST sencilla con Express.

  1. Instalar dependencias:

    npm install express
    
  2. Crear servidor y definir rutas:

    const express = require("express");
    const app = express();
    app.use(express.json());
    
    app.get("/api/usuarios", (req, res) =>
      res.json([{ id: 1, nombre: "Fernando" }])
    );
    
    app.listen(3000, () => console.log("Servidor en puerto 3000"));
    
  3. Probar con Postman o cURL:

    curl http://localhost:3000/api/usuarios
    

10. Explica qué son los middlewares en Express.

Son funciones que se ejecutan antes de llegar a la ruta final, ideales para validaciones, autenticación o logging.

Ejemplo: Middleware de validación

const validarNombre = (req, res, next) => {
  if (!req.body.nombre) return res.status(400).send("Falta el nombre");
  next();
};

app.post("/usuarios", validarNombre, (req, res) => res.send("Usuario creado"));

🔴 Avanzado

11. Gestión de memoria y fugas en Node.js.

Node.js usa V8 Garbage Collector para liberar memoria no utilizada.
Memory leaks ocurren cuando variables no se liberan adecuadamente.

Herramientas para detectarlos:

Ejemplo de fuga:

let datos = [];
setInterval(() => {
  datos.push(new Array(1000000).fill("x")); // No se libera
}, 1000);

12. Problemas de seguridad comunes y mitigaciones.

13. Implementar clustering para múltiples núcleos.

const cluster = require("cluster");
const http = require("http");
const numCPUs = require("os").cpus().length;

if (cluster.isPrimary) {
  for (let i = 0; i < numCPUs; i++) cluster.fork();
} else {
  http.createServer((req, res) => res.end("Servidor activo")).listen(3000);
}

14. Optimizar manejo de archivos evitando bloqueos.

const fs = require("fs");
const readStream = fs.createReadStream("archivo_grande.txt");
readStream.pipe(fs.createWriteStream("nuevo_archivo.txt"));

15. Caso de uso para WebSockets en tiempo real.

Ideal para chats, notificaciones en vivo, juegos multijugador.

Configuración básica:

const { Server } = require("socket.io");
const io = new Server(3000);

io.on("connection", (socket) => {
  console.log("Usuario conectado");
  socket.on("mensaje", (msg) => io.emit("mensaje", msg));
});

Cliente:

const socket = io("http://localhost:3000");
socket.on("mensaje", (msg) => console.log(msg));
socket.emit("mensaje", "Hola!");

🔼 temas