Edgio Applications v4 and support for Node.js 16 are undergoing end-of-life (EOL). Read the Layer0 EOL announcement, the Node.js 16 EOL plan  or browse Edgio Applications v7 docs.
Edgio
Edgio

Static Prerendering

This guide shows you how to configure Edgio to prerender pages to the edge cache and improve the performance of your site.
Edgio allows you to specify the set of URLs that should be prerendered and cached at the edge during deployment to ensure that users get a subsecond experience when accessing your site. Static prerendering works by sending requests to your application code and caching the result right after your site is deployed. In this way, you simply build your app to implement server-side rendering and get the speed benefits of a static site for some or all of your pages. This feature is especially useful for large, complex sites that have too many URLs to prerender without incurring exceptionally long build times.

Specifying the URLs to Prerender

To specify which URLs should be prerendered, use the Router’s prerender function. The prerender function accepts an array of [PrerenderRequest] objects or an async function that returns the same:

Example: Hardcoded Paths

JavaScript
1const { Router } = require('@layer0/core/router')
2
3module.exports = new Router().prerender([
4 // HTML pages
5 { path: '/' },
6 { path: '/categories/mens' },
7 { path: '/categories/mens/shirts' },
8 { path: '/categories/mens/pants' },
9 { path: '/categories/womens' },
10 { path: '/categories/womens/shirts' },
11 { path: '/categories/womens/pants' },
12
13 // API responses
14 { path: '/api/index.json' },
15 { path: '/api/categories/mens.json' },
16 { path: '/api/categories/mens/shirts.json' },
17 { path: '/api/categories/mens/pants.json' },
18 { path: '/api/categories/womens.json' },
19 { path: '/api/categories/womens/shirts.json' },
20 { path: '/api/categories/womens/pants.json' },
21])

Example: Async Paths

JavaScript
1const { Router } = require('@layer0/core/router')
2
3module.exports = new Router().prerender(async () => {
4 const paths = await fetchCategoryPathsFromAPI()
5 return paths.map(path => ({ path }))
6})

Example: Defining Paths via an Environment Variable

JavaScript
1const { Router } = require('@layer0/core/router')
2
3module.exports = new Router().prerender(async () => {
4 const paths = process.env.PRERENDER_PATHS.split(/\n/) // define the list of paths to prerender in the Edgio Developer Console.
5 return paths.map(path => ({ path }))
6})

Prerendering with Traffic Data

Edgio can choose which pages to prerender based on site traffic, ensuring the most popular pages are always available in the edge cache.

Example: Basic Usage

JavaScript
1const { Router } = require('@layer0/core/router')
2
3router = new Router().prerender([
4 {
5 // the maximum number of pages that should be prerendered based on site traffic.
6 top: 50,
7 },
8])

Example: With Cache Splitting

JavaScript
1router = new Router().prerender([
2 // Prerender with language cookie
3 {
4 top: 10,
5 // Request headers that will be passed to your prerender request.
6 // If you're splitting the cache by cookies or headers you can provide them
7 // using headers option.
8 headers: {
9 cookie: 'language=en',
10 },
11 },
12 // Prerender other language
13 {
14 top: 10,
15 headers: {
16 cookie: 'language=de',
17 },
18 },
19])

Prerendering API Calls

To ensure that client-side navigation is as fast as possible, it is important to prerender not just HTML responses but API calls as well. Some frameworks, such as Next.js, embed a build ID in API URLs to ensure the client receives responses from the correct version of the backend. In other frameworks, the convention for how API URLs are structured is left to the developer.

Example: Next.js getServerSideProps

JavaScript
1const { Router } = require('@layer0/core/router')
2const { nextRoutes } = require('@layer0/next')
3const { existsSync, readFileSync } = require('fs')
4const { join } = require('path')
5
6// Read the Next.js build ID from '.next/BUILD_ID'
7const buildIdPath = join(process.cwd(), '.next', 'BUILD_ID')
8
9function getPrerenderRequests() {
10 const prerenderRequests = [
11 { path: '/' },
12 { path: '/categories/mens' },
13 { path: '/categories/mens/shirts' },
14 { path: '/categories/mens/pants' },
15 { path: '/categories/womens' },
16 { path: '/categories/womens/shirts' },
17 { path: '/categories/womens/pants' },
18 ]
19
20 if (existsSync(buildIdPath)) {
21 // Derive the API requests from the HTML page URLs
22 const buildId = readFileSync(buildIdPath, 'utf8')
23 const apiPaths = prerenderRequests.map(path => ({ path: `/_next/data/${buildId}${path}.json` }))
24 prerenderRequests.push(...apiPaths)
25 }
26
27 return prerenderRequests
28}
29
30module.exports = new Router().prerender(getPrerenderRequests).use(nextRoutes)

Advanced Configuration: Custom Cache Keys

If you’re splitting the cache by cookies or headers using a CustomCacheKey, you’ll need to include the cookie or header values in your prerender configuration. For example, if you’re splitting the cache by a language cookie:
JavaScript
1const { Router, CustomCacheKey } = require('@layer0/core/router')
2
3module.exports = new Router()
4 .prerender([
5 // German
6 { path: '/categories/mens', headers: { cookie: 'language=de' } },
7 { path: '/categories/mens/shirts', headers: { cookie: 'language=de' } },
8 { path: '/categories/mens/pants', headers: { cookie: 'language=de' } },
9 { path: '/categories/womens', headers: { cookie: 'language=de' } },
10 { path: '/categories/womens/shirts', headers: { cookie: 'language=de' } },
11 { path: '/categories/womens/pants', headers: { cookie: 'language=de' } },
12
13 // English
14 { path: '/categories/mens', headers: { cookie: 'language=en' } },
15 { path: '/categories/mens/shirts', headers: { cookie: 'language=en' } },
16 { path: '/categories/mens/pants', headers: { cookie: 'language=en' } },
17 { path: '/categories/womens', headers: { cookie: 'language=en' } },
18 { path: '/categories/womens/shirts', headers: { cookie: 'language=en' } },
19 { path: '/categories/womens/pants', headers: { cookie: 'language=en' } },
20 ])
21 .get('/categories/:slug*', ({ cache }) => {
22 cache({
23 key: new CustomCacheKey().addCookie('language'),
24 edge: { maxAgeSeconds: 60 * 60 * 24, staleWhileRevalidate: 60 * 60 * 24 * 365 },
25 })
26 })

Concurrency and Limits

By default, Edgio prerenders a maximum of 200 URLs at a time. This can create significant additional load on your APIs at the time of deployment. You can lower this limit by setting the prerenderConcurrency property in layer0.config.js. Edgio imposes the following limits on prerendering:
TierConcurrencyTotal Number of Requests
ENTERPRISE20025,000 per deployment
FREE10100 per deployment

Viewing Prerendering Results in the Edgio Developer Console

When you deploy a new version of your site, you can view the progress and results of prerendering from the deployment view in Edgio Developer Console:
progress
This section updates in real time as pages are prerendered and will show you any errors that occur. If an error occurs, more information can be found in the build logs.