Regístrate para acceder a más de 15 cursos gratuitos de programación con un simulador

Rutas nombradas JS: Desarrollo web

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

  1. Repite todos los pasos de la lección en tu computadora.
  2. Agrega al programa una clase con los nombres de las rutas.
  3. Cambia el código de los controladores y plantillas para que utilicen rutas nombradas, en lugar de la creación de enlaces manualmente.
  4. Descubre las ventajas de las rutas nombradas.
  5. Modifica las direcciones de los enlaces en la clase con rutas nombradas. Por ejemplo, en lugar de /users haz /u.
  6. 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.
  7. 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.

Obtener acceso
130
cursos
1000
ejercicios
2000+
horas de teoría
3200
test

Obtén acceso

Cursos de programación para principiantes y desarrolladores experimentados. Comienza tu aprendizaje de forma gratuita

  • 130 cursos, 2000+ horas de teoría
  • 1000 ejercicios prácticos en el navegador
  • 360 000 estudiantes
Al enviar el formulario, aceptas el «Política de privacidad» y los términos de la «Oferta», y también aceptas los «Términos y condiciones de uso»

Nuestros graduados trabajan en empresas como:

Bookmate
Health Samurai
Dualboot
ABBYY