Las plantillas del sitio contienen muchas referencias internas, desde el menú hasta los botones y formularios. Hasta ahora, hemos formado estos enlaces directamente en los lugares donde los necesitamos:
if courses.length === 0
p Todavía 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}
Los enlaces también se crean en los controladores, por ejemplo, en las redirecciones:
const id = /* De alguna manera se forma */;
res.redirect(`/courses/${id}`);
En los ejemplos de arriba, la creación del enlace está directamente en el lugar donde se utiliza. Este método de crear enlaces es potencialmente peligroso. ¿Qué pasa si la ruta cambia de /courses/:id a /c/:id? Tendrías que pasar por todas las plantillas y cambiar todos los enlaces /courses/:id a /c/:id. ¿Y si borras esta ruta? El sitio seguirá funcionando, pero los enlaces llevarán a páginas inexistentes. Sería mejor si las páginas con estos enlaces empezaran a dar errores. Entonces será extremadamente fácil identificar tales enlaces.
Rutas nombradas mediante mapeo
Para resolver este problema, inventaron rutas nombradas. Cada ruta del framework se le da un nombre, que luego se puede utilizar al construir un enlace específico. En Fastify, este mecanismo no está integrado, pero se puede imitar fácilmente con un objeto que describe rutas.
const routes = {
usersPath: () => '/users',
newUserPath: () => '/users/new',
coursesPath: () => '/courses',
coursePath: (id) => `/courses/${id}`,
};
Una vez que se añaden los métodos, se pueden insertar en la descripción de las rutas Fastify y pasar a las plantillas:
app.get(routes.newUserPath(), (req, res) => {
// ...
const templateData = {
// ...
routes, // Pasamos al objeto de la plantilla para obtener las rutas
};
res.render('users/new', templateData);
});
app.get(routes.coursesPath(), (req, res) => {
const templateData = {
courses: state.courses,
routes,
};
res.render('courses/index', templateData);
});
app.get(routes.coursePath(':id'), (req, res) => {
// ...
const templateData = {
// ...
routes,
};
res.render('course/index', templateData);
});
app.post(routes.usersPath(), (req, res) => {
// ...
const templateData = {
// ...
routes,
};
res.render('users/index', templateData);
});
Ejemplo de plantilla para imprimir una lista de cursos:
if courses.length === 0
p Todavía no se ha añadido ningún curso
else
each course in courses
div
h2
a(href=routes.coursePath(course.id)) #{course.title}
p #{course.description}
La legibilidad disminuye un poco, pero se puede mejorar agregando comentarios sobre las definiciones de las rutas.
const routes = {
// Usuarios
usersPath: () => '/users',
// Formulario para crear un usuario
newUserPath: () => '/users/new',
// Cursos
coursesPath: () => '/courses',
// Curso específico
coursePath: (id) => `/courses/${id}`,
};
Rutas nombradas con librerías
Existe otro enfoque popular al trabajar con rutas. Se implementa con la ayuda de bibliotecas especiales y permite crear nombres para rutas. Lo veremos con el ejemplo de la biblioteca fastify-reverse-routes:
npm i fastify-reverse-routes
La conexión de la biblioteca a la aplicación se realiza de manera estándar:
import { plugin as fastifyReverseRoutes } from 'fastify-reverse-routes';
// Al crear la aplicación, necesitas especificar esta opción
const app = fastify({ exposeHeadRoutes: false });
await app.register(fastifyReverseRoutes);
Cuando la biblioteca está conectada, podemos obtener la ruta por su nombre, y el nombre de la ruta se establece a través de opciones. Veamos en detalle en el ejemplo de una ruta:
app.get('/users', { name: 'users' }, (req, reply) => {
// ...
});
Hemos creado un controlador y le hemos dado el nombre 'users'. Ahora, en todas partes donde necesitemos obtener la dirección de esta ruta, podemos hacerlo por el nombre dado:
app.reverse('users');
Este método también permite referirse a rutas dinámicas:
app.get('/users/:id/edit', { name: 'editUser' }, (req, reply) => {
// ...
});
app.reverse('editUser', { id: user.id });
Para conveniencia, podemos definir una función auxiliar para las plantillas, para obtener rutas en ellas. Esto se hace con la propiedad defaultContext:
const route = (name, placeholdersValues) => app.reverse(name, placeholdersValues);
await app.register(view, {
engine: { pug },
defaultContext: {
route,
},
});
Llamada en la plantilla:
form(role = 'form' method = 'POST' action = route('users'))
input(type = 'text', name = 'term', value = body)
input(type = 'submit' value = 'Crear')
Trabajo independiente
- Repite todos los pasos de la lección en tu computadora.
- Agrega al programa una clase con los nombres de las rutas.
- Cambia el código de los controladores y plantillas para que utilicen rutas nombradas, en lugar de la creación de enlaces manualmente.
- Descubre las ventajas de las rutas nombradas.
- Modifica las direcciones de los enlaces en la clase con rutas nombradas. Por ejemplo, en lugar de /users haz /u.
- Inicia la aplicación y asegúrate de que continúa funcionando con las nuevas direcciones. Ni siquiera tuvimos que cambiar el código en todos los controladores y plantillas.
- Sube los cambios a GitHub.
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.