3.2 · Motores de plantillas y servicio de archivos

Nivel 3 · Express y bases de datos

3.2Motores de plantillas y servicio de archivos

Objetivo: servir archivos estáticos (express.static) y generar HTML dinámico con un motor de plantillas (res.render), situando a la vez SSR frente a API + front separado.
Tiempo estimado: 10 min · lectura autónoma · Si solo tienes 5 min: lee «Lo esencial en 30s» + el esquema.

Lo esencial en 30 segundos

  • Lo estático se sirve en una línea : app.use(express.static('public')) entrega CSS, imágenes y JS de cliente desde una carpeta dedicada.
  • Lo dinámico se renderiza con un motor : plantillas EJS/Handlebars/Pug + res.render('vista', { datos }) = HTML ensamblado en el servidor (SSR).
  • Dos arquitecturas válidas : SSR para contenido y SEO, API JSON + front separado para apps interactivas — los niveles siguientes se inclinan hacia la API.

Mini-caso hilado — Salim publica el catálogo en SSR y luego en API

Salim, desarrollador junior en Argel, debe publicar el catálogo : fichas de producto en HTML para el posicionamiento, más un cuadro de mando interno muy interactivo. Sirve primero el CSS y las imágenes con express.static('public'), configura EJS (app.set('view engine', 'ejs')) y renderiza res.render('produit', { produit }) para las fichas SSR. Para el cuadro de mando, expone los mismos datos en res.json() : el front dedicado consumirá la API. Un solo servidor, dos renderizados según el uso.

Este mismo caso vuelve en el curso, el esquema, el guion y el reto 48h.

1. Archivos estáticos y plantillas

Una app web entrega recursos fijos (CSS, imágenes, JS de cliente, fuentes) : Express los sirve con el middleware nativo express.static() — app.use(express.static('public')) expone toda la carpeta public/ (una petición hacia /style.css devuelve public/style.css). Se agrupan los assets en esa carpeta dedicada.

Para el HTML dinámico, se usa un motor de plantillas : una plantilla (HTML + variables, bucles, condiciones) rellenada con datos. Los corrientes : EJS (JS en etiquetas <% %>, cercano al HTML), Handlebars/hbs (sintaxis {{ }}, depurada), Pug (indentado, conciso). Se configura (app.set('view engine', 'ejs')), se guardan las vistas en views/, se renderiza con res.render('page', { datos }). Es el SSR (Server-Side Rendering) : el servidor construye el HTML completo y lo envía al navegador.

2. SSR o API + front separado : arbitrar según el proyecto

El SSR conviene a los sitios de contenido (escaparates, blogs, comercio electrónico clásico), al SEO (HTML listo, bien indexable) y a la carga inicial rápida. La alternativa moderna : Node expone una API REST en JSON (sección 4-1) consumida por un front separado (React, Vue, Angular) que muestra en el navegador — ideal para las apps interactivas (cuadros de mando, herramientas) y la experiencia fluida sin recarga.

Ambas son válidas : Salim elige SSR para las fichas (contenido, SEO) y API + front para el cuadro de mando (interactividad). Y el SSR no está superado : vuelve con fuerza vía Next.js/Nuxt que combinan renderizado servidor e interactividad. Los niveles siguientes se inclinan hacia el enfoque API/JSON, dominante en Node.

Error frecuente de interpretación: « El SSR está superado, hay que hacerlo todo en SPA, y express.static sirve también las plantillas ». No. El SSR sigue pertinente (contenido, SEO, simplicidad) y conoce una renovación moderna ; la SPA complica inútilmente un simple sitio escaparate. Y express.static solo sirve los archivos fijos de public/, nunca las vistas de views/ renderizadas por res.render().
¿Estático, SSR o API? Un servidor, tres salidas según la necesidad Estáticoexpress.static : CSS, imágenes+SSRres.render : HTML completo+API + frontres.json : datos para React/Vue Contenido/SEO → SSR ; app interactiva → API + front.
Un servidor, tres salidas según la necesidad
Versión en texto del esquema (SEO / lectores de pantalla / traducción): 1) Estático : Salim coloca CSS e imágenes en public/ servidos por express.static. 2) SSR : EJS renderiza la ficha de producto en HTML completo para el SEO. 3) API : los mismos datos salen en res.json() hacia el cuadro de mando. Lección : se elige el renderizado según el uso, no según la moda.

🔎 Ejemplo concreto — Servir luego renderizar, luego exponer en JSON

Salim cubre las tres salidas con el mismo servidor.

app.use(express.static('public'));
app.set('view engine', 'ejs');
app.get('/produits/:id', (req, res) => {
  res.render('produit', { produit: { id: req.params.id } });
});
app.get('/api/produits/:id', (req, res) => {
  res.json({ id: req.params.id });
});

Lectura : mismo dato, dos renderizados : HTML vía EJS o JSON vía res.json().

Lección : comparar ambos renderizados hace sentir la diferencia SSR frente a API.

Vocabulario de la sección

Archivos estáticos
Recursos fijos (CSS, imágenes, JS de cliente, fuentes) servidos tal cual por express.static('public').

Ejemplo sencillo: El style.css de Salim servido desde public/.

Lo que no es: una vista EJS renderizada con datos.

Reflejo: agrupar todos los assets en public/.

Motor de plantillas
Herramienta que genera HTML dinámico desde plantillas (variables, bucles, condiciones) : EJS, Handlebars, Pug.

Ejemplo sencillo: La ficha de producto EJS de Salim iterando sobre las reseñas.

Lo que no es: una simple carpeta de archivos fijos.

Reflejo: elegir EJS para empezar, cercano al HTML.

res.render()
Método Express que renderiza una vista : res.render('page', { datos }) inyecta los datos en la plantilla de views/.

Ejemplo sencillo: res.render('produit', { produit }) en casa de Salim.

Lo que no es: un envío de JSON en bruto al front.

Reflejo: nombrar la vista como el archivo de views/.

SSR
Server-Side Rendering : el servidor genera el HTML completo y lo envía al navegador ; baza de contenido y SEO.

Ejemplo sencillo: Las fichas de catálogo indexables de Salim.

Lo que no es: una SPA que renderiza todo en el navegador.

Reflejo: privilegiar el SSR para las páginas por posicionar.

API + front separado
Node expone JSON (API REST) consumido por un front React/Vue/Angular que muestra en el navegador.

Ejemplo sencillo: El cuadro de mando interno alimentado en res.json().

Lo que no es: una plantilla EJS renderizada en el servidor.

Reflejo: reservar esta arquitectura a las apps interactivas.

En la práctica — Servir archivos y generar HTML

  1. Servid archivos estáticos con app.use(express.static('public')) : colocad un CSS y una imagen en public/ y comprobad que son accesibles.
  2. Configurad un motor de plantillas (p. ej. EJS : app.set('view engine', 'ejs')) y colocad plantillas en views/.
  3. Renderizad una vista con datos : res.render('page', { titre: '...', items: [...] }) ; en la plantilla, insertad las variables e iterad sobre una lista.
  4. Comparad : renderizad el mismo dato en JSON (res.json(data), enfoque API) para percibir la diferencia SSR frente a API + front separado.
Servís archivos estáticos (express.static) y generáis HTML dinámico con un motor de plantillas (res.render), situando a la vez SSR frente a API + front separado.

Guion listo para decir — justificar SSR frente a API (30 s)

« Las fichas del catálogo salen en SSR con EJS : HTML completo, bueno para el SEO y la primera visualización. El cuadro de mando, muy interactivo, consume el mismo dato en JSON vía nuestra API. Lo estático CSS e imágenes lo sirve express.static desde public. »

Para decir en arbitraje de arquitectura ; mostrar el mismo dato en HTML y luego en JSON.

Modelo copiar-pegar — estático + EJS + JSON

const express = require('express');
const path = require('path');
const app = express();
app.use(express.static('public'));
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
app.get('/produits/:id', (req, res) => {
  res.render('produit', { id: req.params.id });
});
app.get('/api/produits/:id', (req, res) => {
  res.json({ id: req.params.id });
});
app.listen(3000);

Independiente

Un sitio escaparate basta en SSR + estático : sin front pesado para unas pocas páginas.

Pyme en Argel

Salim renderiza las fichas en EJS para el SEO y guarda la API JSON para la admin interna.

Equipo de producto

Separar views/ (SSR) y /api (JSON) para que dos equipos avancen sin conflicto.

Principiante

Esta semana : un CSS servido en estático y una vista EJS con un bucle sobre tres ítems.

✓ Buenas prácticas

  • Servir los assets con express.static (una carpeta public/).
  • Elegir la arquitectura según el proyecto (contenido/SEO frente a app interactiva).
  • Dominar la API REST (JSON) : enfoque dominante de los niveles siguientes.

✗ Errores frecuentes

  • Creer el SSR « superado » (conoce una renovación : Next.js/Nuxt).
  • Elegir una SPA para un simple sitio de contenido (complejidad inútil).
  • Descuidar el SEO en arquitectura SPA pura.

Puntos clave

  • SERVICIO ESTÁTICO : app.use(express.static('public')) sirve los recursos fijos (CSS, imágenes, JS de cliente).
  • MOTORES DE PLANTILLAS (EJS, Handlebars, Pug) : HTML dinámico vía res.render('vista', {datos}).
  • SSR : el servidor genera el HTML completo — enfoque de los sitios clásicos (contenido, SEO).
  • Alternativa moderna muy extendida : Node expone una API REST (JSON) consumida por un FRONT SEPARADO (React/Vue/Angular).

Reto 48h — aplica mañana

Servid 1 CSS en estático y renderizad 1 vista EJS con un bucle sobre 3 ítems.

Lista de salida de la sección
  • Sirvo una carpeta public/ sin dudar.
  • Renderizo una vista con res.render().
  • Arbitrio SSR frente a API según el proyecto.
Autoevaluación 1-5 : ¿están mis vistas en views/ y mis assets en public/?¿sé justificar SSR o API para una necesidad?

Preguntas frecuentes

¿SSR (plantillas) o API + front separado : qué arquitectura elegir?

Ambas son válidas según el proyecto. El SSR conviene a los sitios de contenido (blogs, escaparates, comercio electrónico clásico), cuando el SEO cuenta (HTML entregado listo), para una carga inicial rápida y los sitios poco interactivos (más simple). La API + front separado conviene a las apps interactivas (cuadros de mando, herramientas), a la experiencia fluida sin recarga y a la separación front/back. Salim combina : SSR para las fichas, API para el cuadro de mando.

¿Está superado el renderizado en servidor frente a React?

No, conoce incluso una renovación. Tras la era SSR clásica (plantillas EJS), luego el entusiasmo SPA (todo renderizado en el cliente, con sus límites SEO y de carga inicial), frameworks como Next.js y Nuxt combinan ambos : HTML renderizado servidor (SEO, rapidez) + interactividad cliente (experiencia SPA). El SSR clásico sigue pertinente para muchos sitios por su simplicidad.

Comprueba tu comprensión

¿Qué método Express renderiza una vista con datos?

Recursos adicionales (opcional, para ir más allá)

Examen del nivel 3Preguntas inéditas y más difíciles para validar tus conocimientos