This guide shows you how to deploy a Next.js application to Edgio.
Example
Next.js offers two different file-based routing schemes you can use to build your app. See the Pages Router and App Router sections of the Next.js documentation for more information. Edgio supports both routing schemes with examples of each below:
Supported Features
Edgio supports all of the most powerful features of Next.js, including:
- Static Site Generation (SSG)
- Server Side Rendering (SSR)
- Incremental Static Regeneration (ISR)
- Localization
- Image Optimization
getStaticPaths
(includingfallback: (true|false|'blocking')
)getStaticProps
(includingrevalidate
)getServerSideProps
getInitialProps
Prerequisites
Integration with Next requires:
-
An Edgio account. Sign up for free.
-
An Edgio property. Learn how to create a property.
-
Next.js and Node. Edgio supports the following versions of Next.js and Node.js:
Next.js Version Node.js Version Edgio Version 9.x - 13.x 16.x 7.x 14.x 18.x 7.4.0+ 14.x 20.x 7.5.0+ -
Edgio CLI.
Edgio Applications’s support for Node.js version 16 is undergoing end-of-life. View the end-of-life plan.
Install the Edgio CLI
If you have not already done so, install the Edgio CLI.
Bash
1npm i -g @edgio/cli@latest
Getting Started
Create a Next.js Application
If you don’t already have a Next.js application, you can create one using:
Bash
1npx create-next-app@latest
Initializing your Project
Initialize your project for use with Edgio by running the following command in your project’s root directory:
Bash
1cd my-next-app2edgio init --edgioVersion latest
This will automatically add all of the required dependencies and files to your project. These include:
-
The
@edgio/cli
package - Allows you to control Edgio through project-local CLI. -
The
@edgio/core
package - Allows you to declare routes and deploy your application to Edgio. -
The
@edgio/prefetch
package - Allows you to configure a service worker to prefetch and cache pages to improve browsing speed. -
The
@edgio/devtools
package - Allows you to monitor the caching and prefetching functionality. -
The
@edgio/next
package - Provides router middleware that automatically adds Next.js pages and api routes to the Edgio router. -
The
@edgio/react
package - Provides aPrefetch
component for prefetching pages.edgio.config.js
- Contains various configuration options for Edgio.
-
routes.js
- A default routes file that proxies all requests to the server. Update this file to add caching or proxy some URLs to a different origin. -
sw/service-worker.js
- A service worker implemented using Workbox.
Config Options
In the generated
edgio.config.js
file, you can customize how Edgio builds and runs your Next.js application. Using the next
key, you can configure the following options:Option | Description | Default |
---|---|---|
generateSourceMaps | Output sourcemaps so that stack traces have original source filenames and line numbers when tailing the logs in the Edgio Console. | true |
disableImageOptimizer | Disables the Edgio image optimizer and allows to use the Next’s built in image optimizer. | false |
disableServiceWorker | Disables the build of the service worker. | false |
disablePreviewMode | Disables Next.js’ Preview Mode feature. Preview Mode allows you to bypass edge cache and serve pre-rendered pages. | false |
forceServerBuild | Forces the @edgio/next connector to use the server build. This config option replaces the NEXT_FORCE_SERVER_BUILD env variable. | false |
optimizeServerBuild | Optimizes the server build by bundling all server assets and decreasing the overall startup time. This option has no effect on apps with the Edgio cloud build. This option is set to false for Next 13.x apps. | true |
proxyToServerlessByDefault | Reduces the number of generated rules by adding the default catch-all rule that proxies all requests to Next.js to the Edgio cloud. Set this option to false if you want to proxy all unmatched pages to a different origin. | true |
enforceTrailingSlash | Adds rules with Next’s internal redirects that either add or remove a trailing slash. When set to false , the redirect is performed only by the Next.js server itself and doesn’t affect other origins. | true |
Edgio Next.js Plugin
Edgio provides the following plugin for Next.js. This plugin is automatically added to your project when you run
edgio init
.If your project does not have a
next.config.js
file, one will automatically be added when you run edgio init
. Doing so adds the following plugin:withEdgio (required)
The
withEdgio
plugin optimizes the Next.js build for running on Edgio. It is required to deploy your application on Edgio.If your project already has this config file, you need to add these plugins yourself.
JavaScriptnext.config.js
1const { withEdgio } = require('@edgio/next/config')23module.exports = withEdgio({4 // Next.js config options5})
Running Locally
Test your app with the Sites on your local machine by running the following command in your project’s root directory:
Bash
1edgio dev
Deploying
Deploy your app to the Sites by running the following command in your project’s root directory:
Bash
1edgio deploy
Your initial CDN-as-code deployment will generate system-defined origin configurations along with those defined within your
edgio.config.js
. Learn more about system-defined origins.See Deployments for more information.
Prefetching
The
edgio init
command adds a service worker based on Workbox at sw/service-worker.js
.
If you have an existing service worker that uses workbox, you can copy its contents into sw/service-worker.js
and simply add the following to your service worker:JavaScriptsw/service-worker.js
1import { Prefetcher } from '@edgio/prefetch/sw';23new Prefetcher().route();
The above code allows you to prefetch pages from Edgio’s edge cache to significantly improve browsing speed. To prefetch a page, add the
Prefetch
component from @edgio/react
to any Next.js Link
element. The following example shows you how to prefetch JSON data from getServerSideProps
or getStaticProps
using the createNextDataUrl
function from @edgio/next/client
.JavaScript
1import {Prefetch} from '@edgio/react';2import Link from 'next/link';3import {useRouter} from 'next/router';4import {createNextDataURL} from '@edgio/next/client';56export default function ProductListing({products}) {7 const {locale} = useRouter(); // you can omit this if you're not using localization89 return (10 <ul>11 {products.map((product, i) => (12 <li key={i}>13 <Link href={product.url} passHref>14 <Prefetch15 url={createNextDataURL({16 href: product.url,17 locale, // you can omit this if you're not using localization18 routeParams: {19 // keys must match the param names in your next page routes20 // So for example if your product page is /products/[productId].js:21 productId: product.id,22 },23 })}>24 <a>25 <img src={product.thumbnail} />26 </a>27 </Prefetch>28 </Link>29 </li>30 ))}31 </ul>32 );33}3435export async function getServerSideProps({params: {id}}) {36 const products = await fetch(/* fetch from your api */).then((res) =>37 res.json()38 );3940 return {41 props: {42 products,43 },44 };45}
The
Prefetch
component fetches data for the linked page from Edgio’s edge cache and adds it to the service worker’s cache when the link becomes visible in the viewport. When the user taps on the link, the page transition will be instantaneous because the browser won’t need to fetch data from the network.Registering the Service Worker
To enable prefetching, you need to register the service worker in your app. You can skip this step if your app is already using a service worker. If not, add the following code to your
pages/_app.js
file:JavaScript_app.js
1import {useServiceWorker} from '@edgio/react';2const MyApp = ({Component, pageProps}) => {3 useServiceWorker({4 // set to `true` to install the service worker in development mode5 dev: false,6 });7 // ... rest of your _app.js code8};
Starting with Next.js 13, when the
app
directory is used, adding useServiceWorker
hook may break the build, as all pages in the app
directory are by default server components. In order to avoid this, hooks must be placed in a client-only component. To do this, add use client
directive at the top of the component.Routing
Edgio supports Next.js’s built-in routing scheme. The default
routes.js
file created by edgio init
sends all requests to Next.js:JavaScriptroutes.js
1import {nextRoutes} from '@edgio/next';2import {Router} from '@edgio/core/router';34export default new Router()5 // By default send all requests to the Next.js app6 .use(nextRoutes);
Routing Requests to Other Origins
To route certain requests to an origin other than your Next.js app, first add the origin to
edgio.config.js
:JavaScriptedgio.config.js
1module.exports = {2 connector: '@edgio/next',3 origins: [4 {5 name: 'api',6 hosts: [7 {8 scheme: 'match',9 location: [10 {11 hostname: 'api-origin.myapp.com',12 },13 ],14 },15 ],16 },17 ],18};
Then use the
match
method to define a route and specify the origin
option:JavaScriptroutes.js
1export default new Router()2 // By default send all requests to the Next.js app3 .use(nextRoutes)4 // Override the default behavior to route requests to /api/* to the api origin5 .match('/api/:path*', {6 origin: {7 set_origin: 'api',8 },9 });
Preview Mode
To be able to use Preview Mode while being able to cache the respective pages, update your routes to match the requests that contain the two cookies
__prerender_bypass
& __next_preview_data
, and send those to the Edgio cloud for rendering.JavaScriptroutes.js
1import {Router} from '@edgio/core/router';2import {nextRoutes} from '@edgio/next';34export default new Router()5 // By default send all requests to the Next.js app6 .use(nextRoutes)7 // Disable caching for preview mode8 .match(9 {10 cookies: {11 __prerender_bypass: /.*/g,12 __next_preview_data: /.*/g,13 },14 },15 {16 caching: {17 bypass_cache: true,18 bypass_client_cache: true,19 },20 }21 );
Rewrites and Redirects
The
nextRoutes
plugin automatically adds routes for rewrites and redirects specified in next.config.js
. Redirects are served directly from the network edge to maximize performance.Caching
The easiest way to add edge caching to your Next.js app is to add caching routes after
nextRoutes
. For example,
imagine you have /pages/p/[productId].js
. Here’s how you can SSR responses as well as cache calls to getServerSideProps
:JavaScriptroutes.js
1export default new Router()2 .use(nextRoutes)3 // Products - SSR4 .get('/p/:productId', {5 caching: {6 // Ignore the cache-control header generated by Next.js7 ignore_origin_no_cache: [200],8 // cache at the edge for one day9 max_age: '1d',10 // continue to serve stale responses for up to one hour while revalidating11 stale_while_revalidate: '1h',12 // don't cache the response in the browser13 bypass_client_cache: true14 },15 })16 // Products - getServerSideProps17 .get('/_next/data/:version/p/:productId.json', {18 caching: {19 // Ignore the cache-control header generated by Next.js20 ignore_origin_no_cache: [200],21 // cache at the edge for one day22 max_age: '1d',23 // continue to serve stale responses for up to one hour while revalidating24 stale_while_revalidate: '1h',25 // disable caching in the browser's http cache26 bypass_client_cache: true27 // instead cache in the browser using the service worker for one hour - this allows us to prefetch API calls28 service_worker_max_age: '1h'29 },30 })
Preventing Next.js pages from being cached by other CDNs
If you are using a CDN in front of Edgio and you want to prevent it from caching Next.js pages, you can do so by setting the
bypass_client_cache
option to true
:JavaScriptroutes.js
1new Router()2 // By default send all requests to the Next.js app3 .use(nextRoutes)4 // Disable caching in downstream CDNs for a specific page5 .get('/my-private-page', {6 caching: {7 bypass_client_cache: true, // this will prevent downstream CDNs from caching the response8 },9 });
Using next-i18next
The next-i18next package is a popular solution for adding localization to Next.js apps. It has some issues when running in Edgio cloud deployments, but you can work around these:
First, you need to not use the default name for the
next-i18next.config.js
file. We recommend renaming it i18next.config.js
. When you use the default name, next-i18next will try to load the config when the Cloud Function starts and since it is not bundled with the app, it will fail.Then, you need to explicitly provide the config to
appWithTranslation
and serverSideTranslations
.So in your
pages/_app.js
:JavaScriptpages/_app.js
1export default appWithTranslation(MyApp, require('../i18next.config')); // <~ need to explicitly pass the config here
and in your pages:
JavaScript
1export async function getStaticProps({locale}) {2 return {3 props: {4 ...(await serverSideTranslations(5 locale,6 ['common', 'footer'],7 require('../i18next.config') // <~ need to explicitly pass the config here.8 )),9 // Will be passed to the page component as props10 },11 };12}
Make sure you also import the config correctly with the new name into your
next.config.js
:JavaScriptnext.config.js
1const { withEdgio } = require('@edgio/next/config')2const { i18n } = require('./i18next.config')34module.exports = withEdgio({5 i18n,6 });
Finally, you will need to update your
edgio.config.js
to include where the locale files are stored. Here is an using the default location /public
:JavaScriptedgio.config.js
1module.exports = {2 connector: '@edgio/next',34 serverless: {5 include: ['public/**/*'],6 },7};
Image Optimizer
By default, the Next.js image optimizer is replaced by our image optimizer, which is available in all build modes. However, you can disable our solution and use the built-in Next.js image optimizer instead by adding
disableImageOptimizer: true
to the next
config in the edgio.config.js
file.JavaScriptedgio.config.js
1module.exports = {2 next: {3 disableImageOptimizer: true,4 },5};
Note that Next.js apps prior to 12.x built with the
serverless
target (see Next.js 12.x deprecation notes) don’t include a Next.js image optimizer. Disabling our image optimizer without providing an alternative may cause them to fail.Incremental Static Regeneration (ISR)
Incremental Static Regeneration (ISR) is a feature of Next.js that allows you to update static pages without rebuilding the entire site. To use ISR with Edgio, you need to set the
revalidate
option in getStaticProps
to the desired number of seconds.JavaScriptpages/posts/[id].js
1export async function getStaticProps({params}) {2 const res = await fetch(`https://.../posts/${params.id}`);3 const post = await res.json();45 return {6 props: {7 post,8 },9 revalidate: 60, // In seconds10 };11}
Edgio will automatically revalidate the page after the specified time has passed, and if the page is requested before the revalidation time has passed, the stale page will be served while the new page is being generated.
Cloud Bundling
Next.js has continued to improve how it bundles production builds for deployment on serverless architectures. Edgio takes advantage of these improvements by applying different configuration options depending on the version of Next.js being used:
Version | Next.js configs applied |
---|---|
Next.js < 12.2.0 | target: 'experimental-serverless-trace' |
Next.js >= 12.2.0 | output: 'standalone' |
For backwards compatibility, Edgio will also respect
target: 'serverless'
in your next.config.js for Next.js versions prior to 12.0.0.Note that NextRouter.render404 and renderNextPage are retired when using Next.js 12.2.0+. Requests are delegated to a Next.js server instance which will handle determining which page to render based on the request. Prior use cases should now be achieved via using Next.js redirects and rewrites.
Support for Next.js Middleware (BETA)
Edgio supports Next.js middleware starting with Next.js 12.2.0.
When using Next.js middleware it should be noted that the middleware functions are only executed within the Edgio cloud, after the edge cache. Middleware that you want to execute on each request needs to have caching disabled explicitly for the route on which the middleware is enabled. Some Middleware use cases such as rewriting the request to another route would be fine to cache. These use cases need to be evaluated on a per route basis with caching enabled/disabled based on the desired result.
Runtime Variables Configuration
Edgio supports runtime variables in
serverRuntimeConfig
and publicRuntimeConfig
properties of next.config.js
. For more information, visit the Next.js Runtime Configuration documentation.Related Resources
Below are a few helpful resources that may be referenced in this guide for configuring, managing, and serving your property on Edgio:
- Managing Properties on Edgio Console
- Configuring Hostnames
- Setting up HTTPS Support
- Configuring Origin Configurations
- Firewall - Allowing Edgio IP Addresses
- Serving Traffic through Edgio