Runtimes (NodeJS)
Node.js es un entorno de ejecución de JavaScript de código abierto, basado en el motor V8 de Google Chrome, que permite ejecutar código JavaScript en el lado del servidor. A diferencia de los entornos de JavaScript tradicionales que se ejecutan en navegadores, Node.js posibilita la creación de aplicaciones de servidor, herramientas de línea de comandos y mucho más.
Características Principales
1. Arquitectura Orientada a Eventos
Node.js utiliza un modelo de E/S (Entrada/Salida) no bloqueante y orientado a eventos, lo que lo hace eficiente y adecuado para aplicaciones en tiempo real que necesitan manejar muchas conexiones simultáneas.
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
});
server.listen(3000, () => {
console.log('Servidor corriendo en http://localhost:3000/');
});
2. Monohilo (Single-Threaded) con Bucle de Eventos (Event Loop)
Node.js opera en un único hilo, utilizando un bucle de eventos para gestionar operaciones asíncronas. Esto le permite manejar múltiples conexiones concurrentes sin la sobrecarga de crear nuevos hilos para cada conexión.
3. NPM (Node Package Manager)
NPM es el gestor de paquetes de Node.js, que facilita compartir y reutilizar código. Es uno de los repositorios de software más grandes del mundo, con millones de paquetes disponibles.
# Inicializar un nuevo proyecto
npm init
# Instalar un paquete
npm install express
# Instalar un paquete globalmente
npm install -g nodemon
# Ejecutar scripts definidos en el package.json
npm run start
4. Módulos
Node.js utiliza un sistema de módulos para organizar el código en archivos separados, facilitando el mantenimiento y la reutilización.
// Módulo math.js
exports.add = (a, b) => a + b;
exports.subtract = (a, b) => a - b;
// Uso del módulo
const math = require('./math');
console.log(math.add(5, 3)); // 8
Arquitectura de Node.js
1. Motor V8
V8 es el motor de JavaScript de código abierto desarrollado por Google para Chrome. Node.js utiliza V8 para interpretar y ejecutar código JavaScript.
2. Libuv
Libuv es una biblioteca de E/S asíncrona multiplataforma que proporciona a Node.js acceso al sistema de archivos, la red y otros recursos del sistema operativo de forma no bloqueante.
3. Módulos Nativos
Node.js incluye módulos nativos escritos en C++ que proporcionan funcionalidades de bajo nivel, como acceso al sistema de archivos, red, criptografía, etc.
4. Módulos de JavaScript
La biblioteca estándar de Node.js incluye módulos de JavaScript que proporcionan funcionalidades de alto nivel, como HTTP, HTTPS, FS (sistema de archivos), etc.
Módulos Principales
1. HTTP/HTTPS
Permite crear servidores HTTP y hacer peticiones HTTP.
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
});
server.listen(3000);
2. FS (File System)
Proporciona una API para interactuar con el sistema de archivos.
const fs = require('fs');
// Lectura síncrona
const data = fs.readFileSync('archivo.txt', 'utf8');
console.log(data);
// Lectura asíncrona
fs.readFile('archivo.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
// Usando Promises (Node.js 10+)
const fsPromises = require('fs').promises;
async function leerArchivo() {
try {
const data = await fsPromises.readFile('archivo.txt', 'utf8');
console.log(data);
} catch (err) {
console.error(err);
}
}
3. Path
Proporciona utilidades para trabajar con rutas de archivos y directorios.
const path = require('path');
// Unir segmentos de ruta
const fullPath = path.join('/directorio', 'subdirectorio', 'archivo.txt');
// Obtener el nombre del archivo
const fileName = path.basename(fullPath);
// Obtener la extensión del archivo
const fileExt = path.extname(fullPath);
// Obtener el directorio
const dirName = path.dirname(fullPath);
4. Events
Proporciona una implementación del patrón Observador a través de la clase EventEmitter.
const EventEmitter = require('events');
class MiEmisor extends EventEmitter {}
const emisor = new MiEmisor();
// Registrar un "listener"
emisor.on('evento', (a, b) => {
console.log(a, b);
});
// Emitir un evento
emisor.emit('evento', 'a', 'b');
5. Stream
Proporciona una interfaz para trabajar con flujos de datos.
const fs = require('fs');
// Stream de lectura
const readStream = fs.createReadStream('archivo.txt');
readStream.on('data', (chunk) => {
console.log(`Recibidos ${chunk.length} bytes de datos.`);
});
readStream.on('end', () => {
console.log('Fin de la lectura.');
});
// Stream de escritura
const writeStream = fs.createWriteStream('salida.txt');
writeStream.write('Hello, ');
writeStream.write('World!');
writeStream.end();
// Pipe (encadenamiento de streams)
readStream.pipe(writeStream);
Frameworks y Bibliotecas Populares
1. Express
Express es un framework web minimalista y flexible para Node.js que proporciona un conjunto robusto de características para aplicaciones web y móviles.
const express = require('express');
const app = express();
const port = 3000;
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(port, () => {
console.log(`Aplicación corriendo en http://localhost:${port}`);
});
2. Nest.js
Nest.js es un framework para construir aplicaciones de servidor (server-side) eficientes y escalables en Node.js, inspirado en Angular.
import { Controller, Get } from '@nestjs/common';
@Controller('cats')
export class CatsController {
@Get()
findAll(): string {
return 'This action returns all cats';
}
}
3. Socket.io
Socket.io es una biblioteca que permite la comunicación en tiempo real, bidireccional y basada en eventos entre navegadores web y servidores.
const io = require('socket.io')(server);
io.on('connection', (socket) => {
console.log('Un usuario se ha conectado');
socket.on('chat message', (msg) => {
io.emit('chat message', msg);
});
socket.on('disconnect', () => {
console.log('Usuario desconectado');
});
});
4. Mongoose
Mongoose es una biblioteca de modelado de objetos de MongoDB para Node.js.
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/test');
const Cat = mongoose.model('Cat', { name: String });
const kitty = new Cat({ name: 'Zildjian' });
kitty.save().then(() => console.log('meow'));