El uso de plantillas simplifica significativamente la creación de páginas HTML en el lado del servidor. Pero este enfoque también tiene desventajas. Genera ciertas inconveniencias asociadas con los bloques repetitivos. En esta lección hablaremos sobre este problema y averiguaremos cómo prevenir tales situaciones.
Enfoque invertido para bloques repetitivos
Imagina un sitio web típico. La mayoría de los sitios web tienen un menú superior, un pie de página y muchos bloques repetitivos. ¿Cómo trabajar correctamente con ellos? Parecería que copiar todo esto en cada plantilla no es la mejor idea.
Existe otro enfoque: mover las partes comunes a archivos separados e incluirlos en las plantillas necesarias:
<!-- Ejemplo de un motor de plantillas JSP -->
<%@ include file="parts/header.jsp" %>
<!-- Aquí está el código de la plantilla específica -->
<%@ include file="parts/footer.jsp" %>
Esta es una solución simple que se utilizó en los primeros motores de plantillas. Los desarrolladores rápidamente se dieron cuenta de lo inconveniente que era esto. El problema radica en dos aspectos:
- Incorporaciones manuales: El desarrollador debe incluir manualmente cada elemento en todas las plantillas. En nuestro ejemplo solo hay dos, pero ¿qué pasa si hay cientos? Trabajar con cada plantilla se volvería muy tedioso y consumiría mucho tiempo.
- Revisión de etiquetas: El desarrollador tiene que revisar manualmente diferentes archivos para encontrar etiquetas sin cerrar, ya que estas pueden estar distribuidas en varios archivos. Depurar proyectos así resulta extremadamente complicado.
Estos problemas los resolvió el enfoque invertido, en el cual no se insertan partes del sitio en la plantilla, sino que la plantilla se inserta en el layout del sitio. El principio aquí es el siguiente:
- En un lugar describimos el layout (la base del sitio), que no cambia en estructura.
- El motor de plantillas hace que la plantilla de una página específica se inserte en este layout.
En este caso, la plantilla no sabe nada sobre la estructura del layout, y el layout mantiene todas sus partes en un solo lugar.
Enfoque invertido en PUG
El motor de plantillas PUG admite los layouts. Veamos cómo funciona. Primero, crearemos el layout en src/views/layouts/page.pug:
//- src/views/layouts/page.pug
html
head
meta(charset='utf-8')
meta(name='viewport', content='width=device-width, initial-scale=1')
body
p
a(href='/users')
a(href='/courses')
block content
Prestemos atención a content, que es donde PUG insertará la plantilla de la página específica. Ahora, veamos cómo se ve la plantilla del listado de usuarios:
//- src/views/courses/index.pug
extends ../layouts/page.pug
block content
a(href='/courses/new') New User
each course in courses
div
#{course.title}
Utilizamos la sintaxis extends para incluir el layout en la página deseada. En el ejemplo anterior, hemos especificado la ruta al layout de la plantilla en relación con la plantilla actual.
La característica principal es que incluimos el contenido de la plantilla en una construcción específica, que lo inserta en el lugar correcto en el layout:
block content
Puede parecer redundante. Por otro lado, los creadores del motor de plantillas querían hacer un sistema un poco más avanzado que simplemente insertar en un bloque. Dichas construcciones permiten insertar múltiples bloques en el layout a la vez y pasar los datos de la plantilla específica. Veamos un ejemplo de tal layout y plantilla:
//- page.pug
html
head
title My Web Site
body
block content
block footer
Además de content, este layout usa footer:
extends page.pug
block content
p Welcome
block footer
p Thanks for visiting, come again soon!
El código de la aplicación se verá así:
import fastify from 'fastify';
import view from '@fastify/view';
import pug from 'pug';
const app = fastify();
const port = 3000;
// Conectamos pug a través del plugin
await app.register(view, { engine: { pug } });
const state = {
courses: [
{
id: 1,
titulo: 'JS: Arrays',
descripcion: 'Curso sobre arrays en JavaScript',
},
{
id: 2,
titulo: 'JS: Funciones',
descripcion: 'Curso sobre funciones en JavaScript',
},
],
};
app.get('/courses/:id', (req, res) => {
const { id } = req.params
const course = state.courses.find(({ id: courseId }) => courseId === parseInt(id));
if (!course) {
res.code(404).send({ message: 'Course not found' });
return;
}
const data = {
course,
};
res.view('src/views/courses/show', data);
});
app.get('/courses', (req, res) => {
const data = {
courses: state.courses,
};
res.view('src/views/courses/index', data);
});
app.listen({ port }, () => {
console.log(`Example app listening on port ${port}`);
});
La estructura del archivo de plantillas con layout se ve así:
views
├── layouts
│ └── page.pug
├── cursos
│ ├── edit.pug
│ ├── index.pug
│ ├── new.pug
│ └── show.pug
└── index.pug
Trabajo independiente
- Diseña el sitio con un menú superior que incluya un título y un enlace a la página principal. Añade también un pie de página con un enlace a tu perfil de GitHub.
- Reorganiza las plantillas en tu aplicación de tal manera que utilicen el diseño.
- Comprueba en la práctica las ventajas de los diseños. Intenta hacer varios cambios en el diseño y verifica que los cambios se reflejan inmediatamente en todas las páginas de la aplicación.
- Envía los cambios a GitHub.
Materiales adicionales
Para acceder completo a curso necesitas un plan básico
El plan básico te dará acceso completo a todos los cursos, ejercicios y lecciones de Códica, proyectos y acceso de por vida a la teoría de las lecciones completadas. La suscripción se puede cancelar en cualquier momento.