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:

Versión SIN Static

Versión CON Static

Todo está en app.js

El HTML está SEPARADO en public/index.html

La vista está dentro de res.send()

La vista es un archivo externo

No necesitas carpetas adicionales

Necesitas carpeta public/

El HTML está "duro" en el código

El HTML se puede editar sin tocar el servidor

No se ven los estilos de Bootstrap

Puedes usar Bootstrap fácilmente

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:

  1. Instalar Bootstrap: npm install bootstrap

  2. Crear carpeta public en tu proyecto

  3. Crear index.html dentro de public/ con el código de arriba

  4. Ejecutar: node app.js

  5. 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:

  1. Recibe la solicitud GET /

  2. Como hay express.static('public'), busca en la carpeta public

  3. Busca public/index.html (por convención, busca index.html)

  4. Si existe, lo envía como respuesta

  5. Si no existe, pasa al siguiente middleware o ruta


Cuando alguien escribe: http://localhost:3000/mi-estilo.css

Express hace internamente:

  1. Recibe la solicitud GET /mi-estilo.css

  2. Busca en la carpeta public/mi-estilo.css

  3. Si existe, lo envía con el Content-Type correcto (text/css)

  4. 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:

  1. index.html

  2. index.htm

  3. 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

app.use(express.static('public', { index: false }));

Resumen para alumnos:

Lo que escribes en HTML

Dónde busca Express

href="/styles.css"

public/styles.css

href="/css/estilo.css"

public/css/estilo.css

src="/js/app.js"

public/js/app.js

href="/css/bootstrap.css" (con static('/css', ...))

node_modules/bootstrap/dist/css/bootstrap.css


Comentarios

Entradas más populares de este blog

Cómo Iniciar un Proyecto Node.js

5-Express--Curso de Node.js#05 Introducción a Express.js

8-Template Engines