1. Inicio
  2. Blog
  3. Gestionar rutas dinámicas Nuxt

Gestiona tus rutas dinámicas con Nuxt

Creado el 22/08/2022

Si tienes o quieres montar un sitio web con Nuxt y parte de tus páginas tienen rutas dinámicas puede que hayas encontrado alguna dificultad a la hora de gestionarlas. Te cuento cómo hacerlo de forma sencilla.

Entendiendo las rutas dinámicas

Antes de meterse de lleno en la cuestión principal es importante que tengamos claro qué son y cómo funcionan las rutas dinámicas en Nuxt.

Por defecto Nuxt utiliza vue-router para crear su sistema de rutas de forma que el nombre de cada fichero que incluyamos en el directorio /pages tenga una ruta asociada, es decir, si creamos un fichero con el nombre test.vue en el directorio /pages tendremos la url https://TU_DOMINIO/test disponible.

Cuando queremos crear rutas dinámicas el proceso es parecido pero debemos indicar cual es el directorio raíz del que van a partir las rutas dinámicas, de manera que si tenemos una sección de nuestra web que cataloga especies de animales y queremos que para cada especie exista una página diferente, añadir cada una de ellas a mano puede no ser la mejor opción y querremos tener un sistema automatizado ya sea por un gestor de contenidos o una base de datos que se encargue de ello.

Para este caso, podríamos tener un directorio /animals en el que podemos definir un fichero index.vue que será la página principal de ese directorio, y otro fichero _slug.vue que se encargará de gestionar las páginas dinámicas para cada animal. Esto generaría las siguientes rutas:

  • Ruta principal de animales: https://TU_DOMINIO/animals
  • Rutas dinámicas: https://TU_DOMINIO/animals/lion ó https://TU_DOMINIO/animals/dog

Nomenclatura de ficheros

Al nombrar un fichero empezando con una barra baja (_) le decimos a Nuxt que esa página va a ser dinámica y el nombre que le damos después de la barra baja indica la variable que recibirá el nombre de la ruta (En el ejemplo anterior slug).

Esto es útil de cara a validar si esa ruta existe o no a la hora de acceder a una de estas páginas dinámicas y poder gestionar redirecciones a páginas de error. Por ejemplo podríamos usar el método validate para asegurarnos que el slug es válido o tiene un formato que deseamos, por lo que si el parámetro de ruta slug no cumple las validaciones que queramos el método validate ejecutará la redirección automática a la página de error.

.pages/animals/_slug.vue
export default {
  name: 'AnimalPage',

  validate({ params }) {
    const { slug } = params

    return slug && typeof slug === 'string'
  }
}

Esta validación inicial puede ser muy útil para evitar llamadas innecesarias a nuestro backend para validar una ruta que ya podemos identificar como no válida.

Generando las rutas dinámicas

Es posible que ya tengamos montado nuestro sistema con una gran cantidad de páginas de animales pero si ahora tratamos de desplegar nuestro sitio web en nuestro hosting vamos a observar que todas las rutas dinámicas dan error y nos redirigen a la página de 404. Esto ocurre porque si bien hemos construido y definido nuestro sistema de rutas en tiempo de ejecución, no hemos definido cómo van a generarse estas páginas y por lo tanto no se han creado al ejecutar nuestro proceso de build.

Si tenemos un sitio web estático podemos ver que al ejecutar el comando nuxt generate se crea la página animals pero no las páginas dinámicas y como cada página debe tener su bundle generado en el directorio (por defecto) /dist, todo lo que no esté aquí dará como resultado una redirección a la página 404.

Para solucionar este problema vamos a indicar que en el proceso de generación de nuestro sitio se incluyan todas estas rutas, cosa que debemos indicar porque Nuxt no puede saber cuántos animales tenemos en nuestra base de datos o gestor de contenidos, de modo que vamos a editar el fichero nuxt.config.js y a definir nuestras rutas. Lo primero es crear una función que se va a encargar de consultar las rutas disponibles en nuestra base de datos o gestor de contenido, la cual podemos ubicar en el mismo fichero o extraerla a un fichero de utilidades e importarla:

JS
async function _getRoutes() {
  const response = await fetch('https://www.fakeapi.com/animals', {
    method: 'GET'
  })
  // ['lion', 'dog']
  const animalsList = await response.json()
  const animalsPaths = []

  if (Array.isArray(animalsList)) {
    animalsList.forEach((animalPath) => {
      animalsPaths.push(`/animals/${animalPath}`)
    })
  }

  return animalsPaths
}
  • Asumimos que existe una API llamada "FakeAPI" que nos va a devolver un listado de rutas de animales. Seguramente nuestro sistema nos devuelva otra estructura pero creo que este ejemplo es sencillo para entender lo que debemos hacer
  • Construimos la estructura de rutas relativas y la devolvemos en un Array.

Lo que nos dará un resultado como este:

JS Array
[
  '/animals/lion',
  '/animals/dog'
]

Ahora que tenemos los paths de nuestras rutas dinámicas podemos editar el parámetro generate invocando a la función _getRoutes():

nuxt.config.js
{
  generate: {
    fallback: true,
    async routes() {
      const routes = await _getRoutes($content)

      return routes
    }
  }
}

De esta forma cuando ejecutemos de nuevo el comando nuxt generate se van a generar todas las rutas dinámicas que hemos obtenido de nuestra base de datos o gestor de contenidos.

Consideraciones

Aunque he tratado de poner un ejemplo muy simple, es importante tener en cuenta que este sistema de generación nos puede ayudar a realizar muchos tipos de validaciones. Por ejemplo nuestro sistema de backend podría indicarnos que una ruta está temporalmente inactiva mediante un atributo de cada ruta de animales y podríamos excluirla de la generación.

Hay muchos casos de uso a los que nos enfrentaremos a la hora de construir el routing de nuestra aplicación pero con estos casos básicos seguro que podrás entender el cómo abordarlos.

Si estás utilizando el módulo @nuxt-content para crear tus páginas de contenido puedes utilizar su API para configurar la generación de rutas. Sólo tienes que editar la función _getRoutes() para que reciba la referencia al módulo $content:

JS
async function _getRoutes($content) {
  const animalsList = await $content('animals')
    .fetch()
    .catch(() => {
      return []
    })
  const animalsPaths = animalsList.map((item) => item.path)

  return animalsPaths
}

NOTA: Suponiendo que los ficheros están en el directorio ./content/animals.

Y para terminar modificaríamos el fichero nuxt.config.js de la siguiente forma:

nuxt.config.js
{
  generate: {
    fallback: true,
    async routes() {
      const { $content } = require('@nuxt/content')
      const routes = await _getRoutes($content)

      return routes
    }
  }
}