TechLead
Lección 5 de 6
8 min de lectura
Node.js

Fundamentos de Express.js

Aprende el framework web más popular de Node.js

# Fundamentos de Express.js Express.js es el framework web más popular para Node.js. Simplifica la creación de servidores, manejo de rutas, middleware y mucho más. Es la base de muchas aplicaciones Node.js. ## ¿Por Qué Express? Express.js simplifica el módulo `http` integrado: **Servidor HTTP Plano:** ```javascript const http = require('http'); http.createServer((req, res) => { if (req.url === '/' && req.method === 'GET') { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end('

Hola

'); } }).listen(3000); ``` **Con Express:** ```javascript const express = require('express'); const app = express(); app.get('/', (req, res) => { res.send('

Hola

'); }); app.listen(3000); ``` ## Instalación ```bash # Crear proyecto npm init -y # Instalar Express npm install express # Para desarrollo (opcional) npm install -D nodemon ``` ## Servidor Básico ```javascript const express = require('express'); // Crear aplicación Express const app = express(); // Definir ruta app.get('/', (req, res) => { res.send('¡Hola desde Express!'); }); // Iniciar servidor const PORT = 3000; app.listen(PORT, () => { console.log(`Servidor ejecutándose en http://localhost:${PORT}`); }); ``` ## Enrutamiento ### Métodos HTTP Básicos ```javascript const express = require('express'); const app = express(); // GET - Leer app.get('/users', (req, res) => { res.send('Obtener todos los usuarios'); }); // POST - Crear app.post('/users', (req, res) => { res.send('Crear nuevo usuario'); }); // PUT - Actualizar app.put('/users/:id', (req, res) => { res.send(`Actualizar usuario ${req.params.id}`); }); // DELETE - Eliminar app.delete('/users/:id', (req, res) => { res.send(`Eliminar usuario ${req.params.id}`); }); app.listen(3000); ``` ### Parámetros de Ruta ```javascript // Parámetros de ruta app.get('/users/:id', (req, res) => { const userId = req.params.id; res.send(`Usuario ID: ${userId}`); }); // Múltiples parámetros app.get('/users/:userId/posts/:postId', (req, res) => { const { userId, postId } = req.params; res.send(`Usuario: ${userId}, Post: ${postId}`); }); // Parámetros opcionales app.get('/users/:id?', (req, res) => { if (req.params.id) { res.send(`Usuario: ${req.params.id}`); } else { res.send('Todos los usuarios'); } }); ``` ### Parámetros de Query ```javascript // /search?q=node&category=backend app.get('/search', (req, res) => { const { q, category } = req.query; res.json({ búsqueda: q, categoría: category }); }); // Con valores por defecto app.get('/products', (req, res) => { const page = req.query.page || 1; const limit = req.query.limit || 10; res.json({ página: page, límite: limit }); }); ``` ## Middleware El middleware son funciones que tienen acceso a los objetos request y response: ### Middleware Integrado ```javascript const express = require('express'); const app = express(); // Analizar cuerpo JSON app.use(express.json()); // Analizar datos de formulario codificados en URL app.use(express.urlencoded({ extended: true })); // Servir archivos estáticos app.use(express.static('public')); // Ahora puedes acceder a archivos en carpeta public: // http://localhost:3000/style.css // http://localhost:3000/images/logo.png ``` ### Middleware Personalizado ```javascript // Logger middleware app.use((req, res, next) => { console.log(`${req.method} ${req.url} - ${new Date().toISOString()}`); next(); // Pasar al siguiente middleware }); // Middleware de autenticación function requireAuth(req, res, next) { const token = req.headers.authorization; if (!token) { return res.status(401).json({ error: 'Token requerido' }); } // Verificar token... next(); } // Usar en ruta específica app.get('/dashboard', requireAuth, (req, res) => { res.send('Panel de control'); }); ``` ### Middleware de Manejo de Errores ```javascript // Debe estar después de todas las rutas app.use((err, req, res, next) => { console.error(err.stack); res.status(500).json({ error: 'Algo salió mal!', mensaje: err.message }); }); ``` ## Manejo de JSON ```javascript const express = require('express'); const app = express(); // Habilitar análisis de JSON app.use(express.json()); // Datos de ejemplo let users = [ { id: 1, nombre: 'Juan', email: 'juan@ejemplo.com' }, { id: 2, nombre: 'María', email: 'maria@ejemplo.com' } ]; // GET - Obtener todos los usuarios app.get('/api/users', (req, res) => { res.json(users); }); // GET - Obtener usuario por ID app.get('/api/users/:id', (req, res) => { const user = users.find(u => u.id === parseInt(req.params.id)); if (!user) { return res.status(404).json({ error: 'Usuario no encontrado' }); } res.json(user); }); // POST - Crear nuevo usuario app.post('/api/users', (req, res) => { const newUser = { id: users.length + 1, nombre: req.body.nombre, email: req.body.email }; users.push(newUser); res.status(201).json(newUser); }); // PUT - Actualizar usuario app.put('/api/users/:id', (req, res) => { const user = users.find(u => u.id === parseInt(req.params.id)); if (!user) { return res.status(404).json({ error: 'Usuario no encontrado' }); } user.nombre = req.body.nombre || user.nombre; user.email = req.body.email || user.email; res.json(user); }); // DELETE - Eliminar usuario app.delete('/api/users/:id', (req, res) => { const index = users.findIndex(u => u.id === parseInt(req.params.id)); if (index === -1) { return res.status(404).json({ error: 'Usuario no encontrado' }); } users.splice(index, 1); res.status(204).send(); }); app.listen(3000); ``` ## Archivos Estáticos ```javascript const express = require('express'); const path = require('path'); const app = express(); // Servir archivos desde carpeta 'public' app.use(express.static('public')); // Con prefijo de URL app.use('/static', express.static('public')); // Acceder: http://localhost:3000/static/style.css // Múltiples directorios app.use(express.static('public')); app.use(express.static('uploads')); // Con ruta absoluta app.use(express.static(path.join(__dirname, 'public'))); app.listen(3000); ``` **Estructura de carpetas:** ``` proyecto/ ├── server.js └── public/ ├── index.html ├── style.css ├── script.js └── images/ └── logo.png ``` Acceder archivos: - `http://localhost:3000/index.html` - `http://localhost:3000/style.css` - `http://localhost:3000/images/logo.png` ## Express Router Organiza rutas en módulos separados: **Archivo: routes/users.js** ```javascript const express = require('express'); const router = express.Router(); // Middleware para este router router.use((req, res, next) => { console.log('Solicitud a ruta de usuarios:', Date.now()); next(); }); // Define rutas router.get('/', (req, res) => { res.json({ mensaje: 'Obtener todos los usuarios' }); }); router.get('/:id', (req, res) => { res.json({ mensaje: `Obtener usuario ${req.params.id}` }); }); router.post('/', (req, res) => { res.json({ mensaje: 'Crear usuario', datos: req.body }); }); module.exports = router; ``` **Archivo: routes/posts.js** ```javascript const express = require('express'); const router = express.Router(); router.get('/', (req, res) => { res.json({ mensaje: 'Obtener todos los posts' }); }); router.get('/:id', (req, res) => { res.json({ mensaje: `Obtener post ${req.params.id}` }); }); module.exports = router; ``` **Archivo: server.js** ```javascript const express = require('express'); const app = express(); // Importar routers const usersRouter = require('./routes/users'); const postsRouter = require('./routes/posts'); app.use(express.json()); // Montar routers app.use('/api/users', usersRouter); app.use('/api/posts', postsRouter); // Rutas disponibles: // GET /api/users // GET /api/users/:id // POST /api/users // GET /api/posts // GET /api/posts/:id app.listen(3000); ``` ## Métodos de Response ```javascript app.get('/examples', (req, res) => { // Enviar string res.send('Hola'); // Enviar JSON res.json({ mensaje: 'Hola' }); // Establecer código de estado res.status(404).send('No encontrado'); res.status(201).json({ mensaje: 'Creado' }); // Redirigir res.redirect('/nueva-url'); res.redirect(301, '/nueva-url-permanente'); // Descargar archivo res.download('/ruta/a/archivo.pdf'); // Enviar archivo res.sendFile('/ruta/absoluta/a/archivo.html'); // Establecer encabezados res.set('Content-Type', 'text/html'); res.set({ 'Content-Type': 'text/html', 'X-Custom-Header': 'valor' }); }); ``` ## Ejemplo Completo: API REST ```javascript const express = require('express'); const app = express(); // Middleware app.use(express.json()); // Logger app.use((req, res, next) => { console.log(`${req.method} ${req.url}`); next(); }); // Datos let products = [ { id: 1, nombre: 'Laptop', precio: 999.99 }, { id: 2, nombre: 'Teléfono', precio: 599.99 } ]; // Rutas app.get('/api/products', (req, res) => { res.json(products); }); app.get('/api/products/:id', (req, res) => { const product = products.find(p => p.id === parseInt(req.params.id)); if (!product) { return res.status(404).json({ error: 'Producto no encontrado' }); } res.json(product); }); app.post('/api/products', (req, res) => { const { nombre, precio } = req.body; if (!nombre || !precio) { return res.status(400).json({ error: 'Nombre y precio requeridos' }); } const product = { id: products.length + 1, nombre, precio: parseFloat(precio) }; products.push(product); res.status(201).json(product); }); app.put('/api/products/:id', (req, res) => { const product = products.find(p => p.id === parseInt(req.params.id)); if (!product) { return res.status(404).json({ error: 'Producto no encontrado' }); } product.nombre = req.body.nombre || product.nombre; product.precio = req.body.precio || product.precio; res.json(product); }); app.delete('/api/products/:id', (req, res) => { const index = products.findIndex(p => p.id === parseInt(req.params.id)); if (index === -1) { return res.status(404).json({ error: 'Producto no encontrado' }); } products.splice(index, 1); res.status(204).send(); }); // Middleware de manejo de errores app.use((err, req, res, next) => { console.error(err.stack); res.status(500).json({ error: 'Algo salió mal!' }); }); // Iniciar servidor const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`Servidor ejecutándose en puerto ${PORT}`); }); ``` ## Mejores Prácticas 1. **Usar Middleware**: Extraer lógica común a middleware 2. **Organizar Rutas**: Usar Express Router para aplicaciones grandes 3. **Manejo de Errores**: Implementar middleware de manejo de errores 4. **Validación**: Validar entrada del usuario 5. **Variables de Entorno**: Usar dotenv para configuración 6. **Seguridad**: Usar helmet, cors, rate limiting 7. **Logging**: Usar morgan u otros loggers 8. **Códigos de Estado**: Usar códigos de estado HTTP apropiados ## Middleware Popular ```bash npm install cors helmet morgan dotenv ``` ```javascript const express = require('express'); const cors = require('cors'); const helmet = require('helmet'); const morgan = require('morgan'); require('dotenv').config(); const app = express(); // Middleware de seguridad app.use(helmet()); // Habilitar CORS app.use(cors()); // Logging app.use(morgan('dev')); // Análisis de JSON app.use(express.json()); // Tus rutas aquí... app.listen(process.env.PORT || 3000); ``` ## Recursos - [Documentación de Express](https://expressjs.com/) - [Guía de Express](https://expressjs.com/en/guide/routing.html) - [Middleware de Express](https://expressjs.com/en/resources/middleware.html) ¡Express hace el desarrollo de backend con Node.js mucho más simple! 🚀

Continúa Aprendiendo