nuxt.js static page generator with dynamic pages

nuxt.js Feb 18, 2020

With Nuxt.js you have the choice - will you deliver server side rendered pages over a node.js infrastructure, will you take the single page application approach like a Vue.js app or will you use Nuxt.js as a static site generator with npm run generate?

Static site generation might sound not 2020 but there is nothing faster than static files delivered from a server to your browser. And you do not need a complex infrastructure with node.js or other server side code interpreters. If your website does not have heavily personalized content, needing authorization or something, and you build your website from an api, why not use nuxt.js and npm run generate?

static site generation

By default, Nuxt.js will only generate sites with a static route. Dynamic routes like _slug/index.vue will not be recognized in the static site generation process.

But this is only by default and not a fault. How should Nuxt.js find out all dynamic routes, without giving it a clue, where to search for? Like the song, "How many roads must Nuxt.js walk down... before it knows where to start...".

Let us tell Nuxt.js where to find our roads.

example project

Let us build a static generated client of the dog api (the cat api will work too).
We want to read 20 items of this api, and create a list with all 20 items linked to their detailpages. All set up as static generated sites.

You can find a full working nuxt.js project for this here: github.com/djpogo/nuxt-dynamic-static-page-generator.

dynamic static site generation

Read the configuration-generate documentation api/configuration-generate/#routes and you see that you can tell Nuxt.js which dynamic routes it should build on npm run generate. When your dynamic route uses asyncData() it will be exactly build by static site generation as it would with server side rendering:

// nuxt.config.js
export default {
  generate: {
    routes: [
      '/users/1',
      '/users/2',
      '/users/3'
    ]
  }
}

We can manually tell Nuxt.js which routes we want to be generated, half the problem solved.

The second half is written under the topic configuration-genereate extend api/configuration-build#extend and there is a place, where we can put some javascript code into the static site generation process:

// nuxt.config.js
export default {
  build: {
    extend (config, { isClient }) {
      // Extend only webpack config for client-bundle
      if (isClient) {
        config.devtool = 'source-map'
      }
    }
  }
}

Let us bring these pieces together.

read your api

Hook into the extend(config, context) function and make sure that your code is only run in isServer context:

// nuxt.config.js
module.exports = {
  …
  // add this entry to initialize the routes array
  generate: {
    routes: [],
  },
  …
  build: {
    extend(config, context) {
      if (context.isServer) {
        axios.get('https://api.thedogapi.com/v1/images/search?limit=20&order=Desc')
          .then(({ data }) => {
            // in a minute
          })
          .catch((error) => {
            // oh no
           });
      }
    },
    …
};

build your page tree

Double check the format of your API response. The dog api returns a json array containing all dog entities at first level. If your API response is more tricky you need to adapt your code, but you can handle everything here, even xml, json, csv, plain text...

// nuxt.config.js
…
extend(config, context) {
      if (context.isServer) {
        axios.get('https://api.thedogapi.com/v1/images/search?limit=20&order=Desc')
          .then(({ data }) => {
            data.forEach((detailPage) => {
              this.buildContext.options.generate.routes.push(`/${detailPage.id}`);
            });
          });
      }
    },
    …

Take a look at this.buildContext.options where we fill the generate.routes array, we added to our nuxt.config.js too.

By starting npm run generate we can see, that 21 pages getting generated, 20 of them are delivered from the dog api.

benefits

If search engine optimazation is important, a fast responding and full of rich contents website is mandatory. Hosting static pages on a good configured server (https, http/2, gzip, brotli, zopfli, far future expires, etc) is the way to a good pagespeed.
I think about pagespeed like any visitor in the world. If pagespeed says a page performs good, visitors experience will be good too.

On heavy content sites (hundreds and way more pages) static site generation may take so long that the process needs to rerun every time he has finished, to keep the site up to date. Server side rendering will be the better choice on that scenario.

Article Image from Dawid Zawiła via unsplash and ghost ❤.