The Next.js framework first introduced the pattern of Incremental Static (Re)Generation (commonly referred to as ISG) to the Jamstack community. With ISG, some URLs are rendered at build time, while others aren’t rendered until a user actually visits the page (the app essentially falls back to server-side rendering). A static loading page is returned while server-side rendering is in progress. Individual statically rendered URLs can also be configured to expire after some time (this is the regeneration part).
Edgio provides full support for Incremental Static (Re)Generation, not just on apps built with Next.js (where the @edgio/next
package makes this automatic), but on apps built with any framework.
Adding ISG to Next.js apps
Developers using Next.js don’t need to do anything special to support ISG on Edgio. Simply use the NextRoutes
router plugin:
1// routes.js23const { Router } = require('@edgio/core/router')4const { nextRoutes } = require('@edgio/next')56module.exports = new Router().use(nextRoutes)
Adding ISG to an App Built with any Framework
To enable ISG on any framework, statically render a subset of your app’s pages at build time as well as a static loading page. You can have a single loading page for your app or a separate one for each route. Then, configure your Edgio router to serve the statically rendered pages using serveStatic
. Use the onNotFound
and loadingPage
options to fall back to SSR while displaying the loading page when a request is received for a page that has not been statically rendered.
1// The HTML route2router.get('/products/:id', ({ serveStatic, cache, renderWithApp }) => {3 cache({4 edge: {5 maxAgeSeconds: 60 * 60 * 24, // cache at the edge for 24 hours6 },7 })8 serveStatic('dist/products/:id.html', {9 // When the user requests a page that is not already statically rendered, fall back to SSR.10 onNotFound: () => renderWithApp(),1112 // While SSR is in progress, display a static loading page.13 loadingPage: 'dist/products/loading.html',14 })15})
Your loading page will need to fetch the data to render the full page, so you’ll likely need a data route as well, which can also be statically rendered. When a request has been received for data that has not been statically rendered, the system should block and wait for SSR to finish rather than returning a loading page (since the user is already seeing a loading page). For example:
1// The data route2router.get('/api/products/:id.json', ({ serveStatic, cache, renderWithApp }) => {3 cache({4 edge: {5 maxAgeSeconds: 60 * 60 * 24, // cache at the edge for 24 hours6 },7 })8 serveStatic('dist/products/:id.json', {9 // When the user requests data that is not already statically rendered, fall back to SSR.10 onNotFound: () => renderWithApp(),11 })12})