What is dynamic routing?

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.

How does it work?

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 }))
	}
}

Top Level Routes

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.

Build Time

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}`)
				})
		}
	}
}

Summary

  • Page routes don't need to be set in the code
  • Dynamic routes allow us to set a standard template for a set of pages
  • Easily pull from a CMS using a slug field
  • Tell Nuxt about the dynamic routes to generate the static HTML files