logo Edgio
Products
Solutions
Learn
Company
blog-hero-technology
Blog

A guide to Incremental Static (Re)Generation

By: Rishi Raj Jain | July 13, 2021
Print Article

For understanding Incremental Static Generation, let the explanation be guided by a scenario where a page requested by the user was not pre-rendered while statically exporting the website. In such a case, a fallback page is served while the data loads. Further, upon completion of building the page with the fetched data, the page is then cached onto the server. Any user requesting the page then would skip over the fallback and loading stages, and directly see the built page. Superb!

Regeneration is inspired by the concept of stale-while-revalidate, where stale data is refreshed at regular intervals of 'revalidate' seconds. For pages that have staleWhileRevalidateSeconds value configured, they would be re-built after regular intervals of the configured value.

isg-1

Refer to the detailed guides on ISR at: Incremental Static Regeneration: Its Benefits and Its Flaws and A Complete Guide To Incremental Static Regeneration (ISR) With Next.js.

Getting started with ISG in Nuxt.js with Layer0

This section will describe how to implement ISG with Layer0 and Nuxt.js. The steps include configuring a nuxt app with layer0, creating dynamic page and api routes, and finally using layer0 configurations to see ISG in action.

Configuring Nuxt.js app with Layer0

Create a Nuxt.js app by the following command:

1 npm create nuxt-app layer0-nuxt-isg-example
  • For Choose custom server framework select None

  • For Choose rendering mode select Universal (SSR)(Note: In case you already have a nuxt app, just maintain the above configurations and would be good to go.)

  • Install the Layer0 CLI:

1 npm i -g @layer0/cli
  • In nuxt.config.js, add @layer0/nuxt/module to buildModules:

1 2 3 4 5 module.exports = { ... buildModules: [['@layer0/nuxt/module', { layer0SourceMaps: true }]], ... }
  • Run the following to seamlessly integrate Nuxt 2 with Layer0:

1 layer0 init

Run the Nuxt.js app locally on Layer0

1 layer0 dev

Creating dynamic page and api routes

1. Set up dynamic page routes

Nuxt makes it super easy to create dynamic pages. To set up a dynamic route, create a file _slug.vue in some-route folder in pages directory of your app.

To obtain the dynamic parameter slug, Nuxt provides a data fetching hook asyncData which has access to the context object. For example, in the following pages/some-route/_slug.vue dynamic page, one can obtain the slug via params.slug to make data fetching calls before the page gets rendered.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 export default {   mounted() {     // For a client side transition, fetch the page again to cache it on the edge     if (typeof window !== 'undefined') {       fetch(`/some-route/${this.slug}`)     }   },   async asyncData({ req, params, redirect }) {     let link = undefined     // If in browser (i.e. on client side)     if (typeof window !== 'undefined') {       link = window.location.origin     }     // If on server side (either on Layer0 or on local)     else {       let hostURL = req ? req.headers.host : process.env.API_URL       // You have access to req.headers.host when running npm run dev       // You have access to process.env.API_URL on Layer0 env after deployment, but there is no req header       // Why's that? It's an added benefit of being on Layer0, as the project is compiled with target: 'static',       // Which removes the req object from asyncData in nuxt to produce a full static application.       // This rather is the beauty to ISG with Nuxt.js and Layer0, that you can combine full static site with       // server side capabilities       if (hostURL) {         hostURL = hostURL.replace('http://', '')         hostURL = hostURL.replace('https://', '')         if (hostURL.includes('localhost:')) {           link = `http://${hostURL}`         } else {           link = `https://${hostURL}`         }       }     }     let resp = await fetch(`${link}/api/some-route/${params.slug}.json`)     if (!resp.ok) {       redirect(404, '/error-page')     }     let data= await resp.json()     return {       data,       slug: params.slug     }   }, }

2. Set up dynamic api routes

To set up dynamic api routes, nuxt provides a server middleware can also extend Express which allows creation of REST endpoints. For example, the following server-middleware/rest.js will fetch and return data for all the endpoints that start with /api/some-route/ and ends in .json.

1 2 3 4 5 6 7 8 9 10 11 const express = require('express') const app = express() app.use(express.json()) app.all('/api/some-route/:slug.json', (req, res) => { const slug = req.params.slug // some data fetching calls from the slug res.json({ data: 'data' }) }) module.exports = app

Layer0 ISG Goodies

For ISG, use routes.js (Created automatically by layer0 init command) and add route for the dynamic pages /some-route/_slug.vue and the dynamic api route /api/some-route/:slug.json as below:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 // This file was added by layer0 init. // You should commit this file to source control. let example = "test " + qa const { Router } = require("@layer0/core/router") const { nuxtRoutes } = require("@layer0/nuxt") const IF_PRODUCTION = process.env.NODE_ENV === 'production' module.exports = new Router()   .match("/service-worker.js", ({ serviceWorker }) => {     serviceWorker(".nuxt/dist/client/service-worker.js");   })   .get("/some-route/:slug", ({ cache }) => {     cache({       edge: {         maxAgeSeconds: 60 * 60 * 24 * 365, // keep the incrementally generated page for a year       },       browser: false,     })     if (IF_PRODUCTION)       serveStatic('dist/some-route/:slug.html', {       // When the user requests a page that is not already statically rendered, fall back to SSR.         onNotFound: () => renderWithApp(),       })     else renderWithApp()   })   .get('/api/some-route/:slug.json', ({ serveStatic, cache, renderWithApp }) => {     cache({       edge: {         maxAgeSeconds: 60 * 60 * 24, // cache at the edge for 24 hours       },     })     if (IF_PRODUCTION)       serveStatic('dist/some-route/:slug.json', {       // When the user requests a page that is not already statically rendered, fall back to SSR.         onNotFound: () => renderWithApp(),       })     else renderWithApp()   })   .use(nuxtRoutes)

Testing and Deployment

  • To test locally how the app would do in production, run the following:

1 layer0 build && layer0 run --production

To deploy, run:

1 layer0 deploy
  • Celebrate! 🎉

Example: Incremental Static Generation with Nuxt.js and Layer0

With Layer0, it's easier than ever to implement Incremental Static Generation for different purposes with different frameworks. The following seeks to implement ISG with Nuxt.js via Layer0.

isg2

GitHub: https://github.com/rishi-raj-jain/static-medium-isr-in-nuxtjs-with-layer0 Website: Static Medium

Hero Texture Shield 2000x1220

Move to the Leading Edge

Get the information you need. When you’re ready, chat with us, get an assessment or start your free trial.