6-Middleware?-static('public'
Middleware en Node.js con Express: Guía Definitiva
5-EXPRESS
|
V
6-MIDDLEWARE
. Middleware Clave
Funciones que procesan requests antes de llegar a las rutas.
por ejemplo app.use() es un método que monta middlewares (funciones intermedias) que se ejecutan antes de que lleguen a tus rutas.
Explicación simple:
javascript
// SIN app.use() - La petición va directo a la ruta
app.get('/productos', (req, res) => {
res.send('Productos');
});
// CON app.use() - La petición pasa PRIMERO por el middleware
app.use(express.json()); // ← Middleware global
app.get('/productos', (req, res) => {
// req.body YA fue procesado por express.json()
res.send('Productos');
});
Analogía para entenderlo:
text
Petición del cliente
↓
🛑 app.use() ← "Control de seguridad" (se ejecuta SIEMPRE)
↓
🎯 app.get() ← "Destino final" (solo si coincide la ruta)
Middleware incorporado
javascript
// Parsear JSON
app.use(express.json());
// Parsear formularios
app.use(express.urlencoded({ extended: true }));
// Servir archivos estáticos
app.use(express.static('public'));
Los 3 usos principales:
1. Middlewares globales (se ejecutan para TODAS las rutas)
javascript
app.use(express.json()); // Procesa JSON en TODAS las peticiones
app.use(express.static('public')); // Sirve archivos estáticos
2. Middlewares en rutas específicas
javascript
app.use('/productos', miMiddleware); // Solo para rutas que empiecen con /productos
3. Función personalizada
javascript
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`); // Log de cada petición
next(); // ← Importante: continúa con la siguiente función
});
Regla de oro:
app.use() → Se ejecuta para TODOS los métodos HTTP (GET, POST, PUT, DELETE)
app.get() → Solo para peticiones GET
app.post() → Solo para peticiones POST
Ejemplo visual:
javascript
app.use(express.json()); // ← Para TODAS las rutas
app.use(express.urlencoded()); // ← Para TODAS las rutas
app.get('/productos', ...) // ← Solo para GET /productos
app.post('/productos', ...) // ← Solo para POST /productos
En resumen: app.use() son como "filtros" o "interceptores" que procesan la petición ANTES de que llegue a tu ruta específica.
VERSIÓN 1: SIN STATIC (La vista está en la ruta - Todo junto)
javascript
const express = require('express');
const app = express();
const PORT = 3000;
// Datos de ejemplo
const productos = [
{ id: 1, nombre: 'Laptop', precio: 1000 },
{ id: 2, nombre: 'Mouse', precio: 25 },
{ id: 3, nombre: 'Teclado', precio: 50 }
];
// ============ RUTAS SOLO GET ============
// GET - Obtener todos los productos
app.get('/productos', (req, res) => {
res.json({
success: true,
cantidad: productos.length,
productos: productos
});
});
// GET - Obtener un producto específico por ID
app.get('/productos/:id', (req, res) => {
const id = parseInt(req.params.id);
const producto = productos.find(p => p.id === id);
if (!producto) {
return res.status(404).json({ error: 'Producto no encontrado' });
}
res.json(producto);
});
// Ruta principal - La VISTA está AQUÍ dentro del código
app.get('/', (req, res) => {
res.send(`
<h1>API de Productos - Solo GET</h1>
<h3>Endpoints disponibles:</h3>
<ul>
<li><a href="/productos">GET /productos</a> - Ver todos los productos</li>
<li>GET /productos/:id - Ver un producto específico</li>
</ul>
<h3>Ejemplos:</h3>
<ul>
<li><a href="/productos/1">Ver producto ID 1</a></li>
<li><a href="/productos/2">Ver producto ID 2</a></li>
<li><a href="/productos/3">Ver producto ID 3</a></li>
</ul>
`);
});
// Iniciar servidor
app.listen(PORT, () => {
console.log(`🚀 Servidor corriendo en http://localhost:${PORT}`);
console.log(`📦 Ver productos: http://localhost:${PORT}/productos`);
});
Express reemplaza la URL con la ruta de la carpeta que configuraste en express.static() 🎯Añadir soporte para archivos estáticos (Recomendada)
javascript
const express = require('express');
const app = express();
const PORT = 3000;
// ============ MIDDLEWARE STATIC ============
// Servir archivos estáticos desde la carpeta 'public'
app.use(express.static('public'));
// Opcional: Servir Bootstrap desde node_modules (como tu ejemplo)
app.use('/css', express.static('node_modules/bootstrap/dist/css'));
app.use('/js', express.static('node_modules/bootstrap/dist/js'));
// Datos de ejemplo
const productos = [
{ id: 1, nombre: 'Laptop', precio: 1000 },
{ id: 2, nombre: 'Mouse', precio: 25 },
{ id: 3, nombre: 'Teclado', precio: 50 }
];
// ============ RUTAS SOLO GET ============
// GET - Obtener todos los productos
app.get('/productos', (req, res) => {
res.json({
success: true,
cantidad: productos.length,
productos: productos
});
});
// GET - Obtener un producto específico por ID
app.get('/productos/:id', (req, res) => {
const id = parseInt(req.params.id);
const producto = productos.find(p => p.id === id);
if (!producto) {
return res.status(404).json({ error: 'Producto no encontrado' });
}
res.json(producto);
});
// Ruta principal (ahora puedes servir un HTML bonito)
app.get('/', (req, res) => {
res.sendFile(__dirname + '/public/index.html');
});
// Iniciar servidor
app.listen(PORT, () => {
console.log(`🚀 Servidor corriendo en http://localhost:${PORT}`);
console.log(`📦 Ver productos: http://localhost:${PORT}/productos`);
console.log(`🎨 Ver interfaz: http://localhost:${PORT}`);
});
Luego creas public/index.html:
html
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mi Tienda API</title>
<!-- Usando Bootstrap desde node_modules gracias a static middleware -->
<link rel="stylesheet" href="/css/bootstrap.min.css">
</head>
<body>
<div class="container mt-5">
<h1 class="text-center">📦 Mi Tienda de Productos</h1>
<div class="row mt-4">
<div class="col-md-6 offset-md-3">
<div class="card">
<div class="card-header">
<h3>Productos disponibles</h3>
</div>
<div class="card-body">
<div id="productos"></div>
</div>
</div>
</div>
</div>
</div>
<script src="/js/bootstrap.min.js"></script>
<script>
// Consumir tu API desde el frontend
fetch('/productos')
.then(response => response.json())
.then(data => {
const productosDiv = document.getElementById('productos');
if(data.success) {
const lista = document.createElement('ul');
lista.className = 'list-group';
data.productos.forEach(producto => {
lista.innerHTML += `
<li class="list-group-item">
<strong>${producto.nombre}</strong> - $${producto.precio}
<a href="/productos/${producto.id}" class="btn btn-sm btn-primary float-end">Ver</a>
</li>
`;
});
productosDiv.appendChild(lista);
}
});
</script>
</body>
</html>
DIFERENCIAS CLAVE PARA EXPLICAR A LOS ALUMNOS:
Estructura de carpetas para la versión CON Static:
text
tu-proyecto/
├── app.js
├── public/
│ └── index.html
├── node_modules/
│ └── bootstrap/
└── package.json
Pasos para probar la versión CON Static:
Instalar Bootstrap: npm install bootstrap
Crear carpeta public en tu proyecto
Crear index.html dentro de public/ con el código de arriba
Ejecutar: node app.js
Abrir: http://localhost:3000
¿Cómo sabe express.static() qué archivo servir?
Concepto clave: Mapeo automático
Cuando usas app.use(express.static('public')), Express automáticamente mapea:
text
URL solicitada → Archivo en el servidor
"/" → "public/index.html"
"/styles.css" → "public/styles.css"
"/js/script.js" → "public/js/script.js"
"/images/logo.png" → "public/images/logo.png"
NO se lo especificas en ninguna parte, Express busca automáticamente el archivo en la carpeta public basado en la URL.
Ejemplo práctico paso a paso:
Tu código:
javascript
app.use(express.static('public'));
Cuando alguien escribe en el navegador: http://localhost:3000/
Express hace internamente:
Recibe la solicitud GET /
Como hay express.static('public'), busca en la carpeta public
Busca public/index.html (por convención, busca index.html)
Si existe, lo envía como respuesta
Si no existe, pasa al siguiente middleware o ruta
Cuando alguien escribe: http://localhost:3000/mi-estilo.css
Express hace internamente:
Recibe la solicitud GET /mi-estilo.css
Busca en la carpeta public/mi-estilo.css
Si existe, lo envía con el Content-Type correcto (text/css)
Si no existe, responde con error 404
¿Cómo vincular CSS en tu HTML?
Opción 1: CSS directamente en la raíz de public
Estructura:
text
public/
├── index.html
└── styles.css
En index.html:
html
<link rel="stylesheet" href="/styles.css">
Explicación: /styles.css = busca public/styles.css
Opción 2: CSS en subcarpeta
Estructura:
text
public/
├── index.html
└── css/
└── styles.css
En index.html:
html
<link rel="stylesheet" href="/css/styles.css">
Explicación: /css/styles.css = busca public/css/styles.css
Opción 3: CSS desde node_modules (como Bootstrap)
Código:
javascript
app.use('/css', express.static('node_modules/bootstrap/dist/css'));
Estructura:
text
node_modules/
└── bootstrap/
└── dist/
└── css/
└── bootstrap.min.css
En index.html:
html
<link rel="stylesheet" href="/css/bootstrap.min.css">
Explicación:
El prefijo /css se reemplaza por node_modules/bootstrap/dist/css
/css/bootstrap.min.css = busca node_modules/bootstrap/dist/css/bootstrap.min.css
¿Por qué no necesitas especificar "index.html"?
Express tiene una convención incorporada: cuando una carpeta estática recibe una solicitud a /, automáticamente busca:
index.html
index.htm
default.html (si se configura)
Puedes cambiar este comportamiento:
javascript
// Cambiar el archivo por defecto
app.use(express.static('public', { index: 'home.html' }));
// Deshabilitar el index automático
Comentarios
Publicar un comentario