How to Generate Dynamic Routes in Nuxt.js

How to Generate Dynamic Routes in Nuxt.js

by Jason Lewis on Mar 24, 2019

SITE NAME CHANGE: Hi there, this is just a quick note to explain why the site name seems to have changed. I've decided that my personal domain of Gecko8 wasn't nearly descriptive enough. I want to cover not just code, but how to make our lives better as developers. With that goal in mind, I feel Life And Code is a better choice. I hope you agree!

Have you ever used Nuxt.js, the static site generator for Javascript and Vue, to generate a static website? If not, this article probably won't interest you in the slightest! If you have, you may have run into the case where out of the box, Nuxt will generate all predefined routes but not your dynamic ones. By dynamic I mean routes that use a parameter to create the route. Some examples would be a page id, or in the case of a blog, the post slug. Here's an example from the project for this website:

Nuxt basic file structure

In it's standard configuration, Nuxt will create the following routes:

  • /
  • /blog

But not the routes for specific posts (the _slug.vue) file. For example, the following route won't be generated as a static file:

  • /blog/how-to-generate-dynamic-routes-in-nuxt-js

If you're like me and new to static sites, you many not have even noticed the problem. The only reason I knew something was wrong is that anytime I refreshed a blog post or had someone navigate to it from the direct link, a page not found error would appear. Not an ideal scenario! This actually makes sense since Nuxt itself has no knowledge of where you're getting the dynamic data from so it can't guess what all the possible routes might be.

Well, I'm here to show you how to tell Nuxt what dynamic routes need to be generated too! Let's get started.

Let's Get Started

First I want to break down the process into the two main steps:

  1. Get a list of all the dynamic ids (In my case, blog post slugs)
  2. Tell Nuxt what routes to build

Both of these steps will be added in your nuxt.config.js in the generate propery in a routes function:

generate: {
    routes: (callback) => {
        // 1. Get the list of posts
        ...

        // 2. Build the list of routes for Nuxt
        ...
    }
}

Psst, take note of that "callback" parameter, that will be important later.

1. Get the List of Dynamic Data

For this blog I'll pull the list of slugs for my blog posts but the ids could really be anything. I'll also be using a GraphQL query to pull them from my Dato CMS backend but you could just as easily be using an Ajax call to a custom API, or even reading from static files stored in your repository.

Here's my code to pull the list of blog slugs from Dato CMS:

// 1. Get the list of posts
const uri = 'https://graphql.datocms.com';
const link = new createHttpLink({ uri: uri, fetch: fetch });
const operation = {
    query: gql`
    {
        allBlogPosts {
            id
            slug
        }
    }`,
    context: {
        headers: {
            authorization: 'Bearer ...'
        }
    }
};
let data = await makePromise(execute(link, operation));

Effectively, I'm grabbing the list of blog information from DatoCMS (but it could be any data source). makePromise is just a helper provided by Apollo (main library for calling GraphQL) that converts the query execution into a promise for easier consumption.

The important bit is that we end up with an array of results something like this:

[
    { id: 1, slug: 'my-blog-post-about-cats-programming' },
    { id: 2, slug: 'another-blog-post-about-why-cats-shouldnt-program' }
]

Don't get too hung up on all that GraphQL stuff, it really doesn't matter how you create your list of data. Now on to the next step!

2. Tell Nuxt What Routes to Build

This is the easy part. Remember that "callback" parameter we noted earlier? That's how we give Nuxt the list of dynamic routes to build. Here's my code for step 2:

// 2. Build the list of routes for Nuxt
const postRoutes = data.data.allBlogPosts.map(item => {
    return `/blog/${item.slug}`;
});

// Register the routes
callback(null, postRoutes);

Really I'm just doing two things. Creating a list of the dynamic routes and then telling Nuxt about them. If you'd prefer to use less new Javascript syntax like map and arrow functions, it could also look something like this:

// 2. Build the list of routes for Nuxt
var postRoutes = [];
data.data.allBlogPosts.forEach(function(item) {
    postRoutes.push('/blog/' + item.slug);
});

// Register the routes
callback(null, postRoutes);

That's all there is to it! Now if we run the generate command we can see in the output that the blog routes are being generated as well. No more 404 errors and everything runs lightning fast.

ℹ Generating pages
✔ Generated /
✔ Generated /blog
✔ Generated /blog/vue-code-auto-formatting-in-visual-studio-code

More information: Official Docs on nuxt.config.js routes