One of the strongest features of most static site generators is dynamic routing. And we can easily eachieve this in Nuxt.
Let's say you have a blog with 3 posts. The easiest way to set this up without a CMS is to set your files up like so:
pages/
blog/
- my-first-post.vue
- another-post.vue
- this-is-my-last-post.vue
You'd then populate each page individually. But let's say you have 300 posts, a content management system and the need for consistency. Dynamic routing will allow you to set one template for all posts.
With dynamic routing you set a single template that fetches the content based on a parameter, such as the URL slug. Here's how we do it in Nuxt.
pages/
blog/
- _slug.vue
The underscore tells Nuxt that this is a dynamic route. slug
is a placeholder for the slug that will be used in the real world. So let's say you have a post in your CMS with a slug field value of "my-dynamic-post" and your user tries to access yoursite.com/blog/my-dynamic-post.
Nuxt will access "my-dynamic-post" through the context.params.slug
property, which you'd use to query your CMS for the matching page. Here's an example using asyncData:
export default {
asyncData(context) {
return axios.get(
'my-cms-api.com/getPosts',
{ where: { slug: context.params.slug } }
)
.then((response) => response.data.posts[0])
.catch(() => context.error({ statusCode: 404 }))
}
}
One of the biggest questions I had when first researching dynamic routing is top level pages. Every tutorial used subdirectories, such as /blog. What if I wanted to have a dynamic page without pushing it under a /blog subdirectory? Here's how:
pages/
- _slug.vue
Just have the _slug.vue
file on the top level pages directory. It'll now allow you to have mysite.com/custom-dynamic-page. It's as simple as that.
If you're deploying your Nuxt application as a Universal App (delivering static HTML pages and then rehydrating on the client side) then you'll need to tell Nuxt about the dynamic routes.
You can do this through the generate.routes
property in nuxt.config.js
.
export default {
generate: {
routes: [
'/dynamic-page',
'/blog/dynamic-post'
]
}
}
Obviously when you have 300 posts you can't statically set the routes in the array above. So that's why you can use generate.routes
as an asynchronous function, allowing you to query your CMS for all current routes.
This just queries all pages and returns an array that looks like the static array noted above.
export default {
generate: {
routes() {
return axios.get('my-cms-api.com/getPosts')
.then(({ data }) => {
return data.posts.map(({ slug }) => `/blog/${slug}`)
})
}
}
}