- Cómo comenzar a trabajar con PUG 🐾
- Cómo funciona la representación de datos
- ¿Qué estructuras de control se utilizan en Pug?
En esta lección nos familiarizaremos con los motor de plantillas.
Fastify y otros frameworks similares permiten crear sitios web completos sin herramientas adicionales. Un sitio web funcional simplemente debe devolver una respuesta con código HTML, que el navegador mostrará como una página:
app.get('/', (req, res) => {
res.type('html');
res.send('<h1>Hello World!</h1>');
});
Aquí vemos un ejemplo simplificado, en el que solo devolvemos un encabezado H1.
En las aplicaciones reales, el HTML devuelto consta de cientos y miles de líneas. Trabajar con estos volúmenes de la manera estándar es muy complicado. Aquí están solo algunos de los problemas que encontraremos:
- Este código es difícil de formar, editar y mantener.
- Es muy fácil cometer un error en este código y es muy difícil detectarlo.
- En este código pueden surgir problemas con comillas simples o dobles; será necesario manejar adecuadamente estos caracteres y mantener una vigilancia constante.
Para resolver este problema se utilizan los motores de plantillas. Son bibliotecas que permiten generar HTML en archivos separados, con resaltado y sustitución de datos de manera conveniente. En otras palabras, obtenemos no HTML dentro del código, sino código dentro del HTML.
En el mundo de Fastify existen varios motores de plantillas diferentes. Para este curso elegimos Pug.
Veamos cómo se ve una plantilla en PUG:
doctype html
html(lang='en')
head
title Hello, World!
body
h1 Hello, World!
div.remark
p Pug rocks!
Cómo comenzar a trabajar con PUG 🐾
Para comenzar a trabajar con pug en Fastify, debes instalar dos paquetes:
npm i pug @fastify/view
El paquete @fasitfy/view agrega soporte para motores de plantillas en Fastify. Cuando se conecta el complemento, debes indicar que deseas usar Pug como el motor de plantillas en nuestra aplicación:
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 complemento
await app.register(view, { engine: { pug } });
app.listen({ port }, () => {
console.log(`Example app listening on port ${port}`);
});
Las plantillas Pug se almacenan en el directorio src/views y tienen la extensión pug. Para practicar, vamos a agregar la primera plantilla para la página principal del sitio web. Para ello, realizaremos dos acciones:
Crearemos la plantilla src/views/index.pug con el siguiente contenido:
doctype html html(lang='en') head title Hello Códica! body main h1 Hello, World! p Fastify + PugIndicaremos al controlador de la página principal que use esta plantilla:
app.get('/', (req, res) => res.view('src/views/index'));
Fíjate en el método res.view() en el código anterior. Se encarga de renderizar la plantilla especificada y agregar el resultado a la respuesta HTTP.
La ruta a la plantilla se especifica en relación a la directorio raíz de la aplicación:
# Por ejemplo, la estructura puede verse así
views
├── cursos
│ ├── edit.pug
│ ├── index.pug
│ ├── new.pug
│ └── show.pug
├── index.pug
└── usuarios
├── edit.pug
├── index.pug
└── new.pug
Las propias plantillas pueden ubicarse a un nivel más profundo. Esto se vuelve importante cuando aumenta el número de plantillas.
El motor de plantillas no establece reglas de nombrado y estructura interna de las plantillas. Pero trabajar sin reglas es demasiado complicado, por lo tanto, con el tiempo desarrollaremos nuestras propias reglas y las seguiremos.
Cómo funciona la representación de datos
Por lo general, el HTML dentro de las plantillas se genera a partir de datos que queremos mostrar. Por ejemplo, para mostrar información sobre un curso en la página /cursos/:id, pasamos un objeto de ese curso a la plantilla y generamos el HTML en base al contenido del mismo.
Veamos cómo los controladores normalmente trabajan con plantillas:
- Primero extraen todos los datos que necesitan.
- Luego crean un objeto con los datos para la plantilla.
- Finalmente pasan este objeto a la plantilla como un objeto.
const state = {
cursos: [
{
id: 1,
titulo: 'JS: Arrays',
description: 'Curso sobre arrays en JavaScript',
},
{
id: 2,
titulo: 'JS: Funciones',
description: '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);
});
Queda un último paso: mostrar los datos del curso en la plantilla. Para hacerlo, en las plantillas tenemos acceso al objeto que pasamos en el controlador:
doctype html
html
head
title Hello Códica!
body
main
h1= course.title
p= course.description
¿Qué estructuras de control se utilizan en Pug?
Aparte de la salida normal de valores, en las plantillas a menudo se utilizan estructuras de control y bucles. Con su ayuda, se muestran listas, se ocultan o se muestran bloques específicos, etc.
Puedes leer más sobre todas estas estructuras en la documentación oficial. Pero aquí desglosaremos un ejemplo basado en la ruta /cursos, en la cual se muestra una lista de cursos con descripciones y enlaces a los cursos.
Controlador de la ruta:
app.get('/courses', (req, res) => { const data = { courses: state.courses, // En algún lugar se almacena una lista de cursos header: 'Cursos de programación', }; res.view('src/views/courses/index', data); });Plantilla
html head title Códica body h1= header if courses.length === 0 p Aún no se ha añadido ningún curso else each course in courses div h2 a(href=`/courses/${course.id}`)= course.title p= course.description
La lógica de salida aquí es la siguiente:
- Si la lista de cursos está vacía, se muestra un mensaje correspondiente.
- Si hay cursos en la lista, se generan bloques HTML con información del curso y enlaces a su página a partir de esta lista.
Estas estructuras son suficientes para resolver la mayoría de las tareas estándar.
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.