Our CDN-as-code approach to configuration allows you to configure CDN behavior using EdgeJS within a file (routes.[js|ts]
) stored alongside your code. This allows you to leverage the power of source control for collaboration and to link your CDN configurations with specific versions of your web application.
Quick Start
Get started with CDN-as-code by:
-
Creating and deploying a property to Edgio.
Alternatively, you may experiment with our sample websites by deploying them to Edgio.
-
Use the Edgio CLI to initialize your property.
This step requires Node.js v16.x.
Install the Edgio CLI, initialize your property, and then deploy it by running the following command from the root directory of your web application or website:
Bash1npx @edgio/cli@latest init \2--name <PROPERTY> \3--deploy -
Define routes that determine how Edgio will handle that traffic.
-
Deploy your property to the Edgio network.
Routes.js|ts File
The routes.[js|ts]
file defines a set of routes. A route:
- Identifies a set of requests by HTTP method, URL path, query string parameters, cookies, and request headers.
- Determines how our CDN will handle the above requests. For example, you may configure those requests to be cached, prefetched, passed through without modification, or served as static content.
By default, our CLI automatically creates routes.js
and edgio.config.js
upon initializing a property (edgio init
). If your web application supports TypeScript and it uses a framework for which we have a TypeScript implementation, then our CLI will create routes.ts
instead of routes.js
.
Default Route Configuration
By default, your routes.[js|ts]
contains the following configuration:
1import {Router} from '@edgio/core/router';23// const ONE_HOUR = 60 * 604// const ONE_DAY = 24 * ONE_HOUR56export default new Router()78 // Here is an example where we cache api/* at the edge but prevent caching in the browser9 // .match('/api/:path*', ({ proxy, cache }) => {10 // cache({11 // edge: {12 // maxAgeSeconds: ONE_DAY,13 // staleWhileRevalidateSeconds: ONE_HOUR,14 // },15 // browser: {16 // maxAgeSeconds: 0,17 // serviceWorkerSeconds: ONE_DAY,18 // },19 // })20 // proxy('origin')21 // })2223 // send any unmatched request to origin24 .fallback(({proxy}) => proxy('origin'));
The above configuration proxies all requests that do not match a route to the origin
backend. Additionally, it does not define a route, since the only match()
method has been commented-out. This means that all requests will be proxied to the origin
backend.
A backend identifies a domain or IP address to which Edgio may proxy requests. In this case, the origin
backend was defined when you initialized this property using the edgio init
command.
Add, modify, and remove backends by editing the edgio.config.js file.
Routes
A route identifies a set of requests through any combination of URL path, HTTP method, cookies, request headers, and query string parameters. The following routes show various ways for identifying requests.
-
Match all requests:
JavaScript1.match('/:path*', () => {2 // route handler goes here3}) -
Match all
GET
requests whose URL path starts with/marketing/images/
:JavaScript1.get('/marketing/images/:path*', () => {2 // route handler goes here3}) -
Match all
GET
andPOST
requests whose URL path starts with/marketing/images/
and contain thesport
request header set tobasketball
:JavaScript1.match(2 {3 path: '/marketing/images/:path*',4 method: /GET|POST/i, // regular expression5 headers: { 'sport': /^basketball$/i }, // keys are header names; values are regular expressions6 },7 () => {8 // route handler goes here9})
Once you have identified a set of requests, you need to define how Edgio will handle those requests. The following routes show various ways in which requests can be processed.
- Apply a caching policy to all requests and proxy cache misses to the
origin
backend:JavaScript1.match('/:path*', ({ proxy, cache }) => {2 cache({3 edge: {4 maxAgeSeconds: 36005 }6 })7 proxy('origin')8}) - Set the
images
response header and proxy cache misses to theorigin
backend for all GET requests whose URL path starts with/marketing/images/
:JavaScript1.get('/marketing/images/:path*', ({ setResponseHeader, proxy }) => {2 setResponseHeader('images', 'true')3 proxy('origin')4})
Defining Routes
We will now define a route by uncommenting the constants and the match()
method in your routes.[js|ts]
file. It should now look similar to the following configuration:
1import {Router} from '@edgio/core/router';23const ONE_HOUR = 60 * 60;4const ONE_DAY = 24 * ONE_HOUR;56export default new Router()78 // Here is an example where we cache api/* at the edge but prevent caching in the browser9 .match('/api/:path*', ({proxy, cache}) => {10 cache({11 edge: {12 maxAgeSeconds: ONE_DAY,13 staleWhileRevalidateSeconds: ONE_HOUR,14 },15 browser: {16 maxAgeSeconds: 0,17 serviceWorkerSeconds: ONE_DAY,18 },19 });20 proxy('origin');21 })2223 // send any unmatched request to origin24 .fallback(({proxy}) => proxy('origin'));
The above route matches all requests that start with /api/
and instructs Edgio to:
- Cache those requests on our network for one day.
- Allow us to serve stale content for one hour.
- Instruct the browser to treat the response as immediately stale.
- Allow prefetched requests to be served from cache for one day.
- Proxy those requests to your
origin
backend when we cannot serve them from cache.
You can use constants to apply this same caching policy to various routes. Define a CACHE_ASSETS
constant and set it to the cache
object defined in the above route.
1import { Router } from '@edgio/core/router'23 const ONE_HOUR = 60 * 604 const ONE_DAY = 24 * ONE_HOUR5 const CACHE_ASSETS = {6 edge: {7 maxAgeSeconds: ONE_DAY,8 staleWhileRevalidateSeconds: ONE_HOUR,9 },10 browser: {11 maxAgeSeconds: 0,12 serviceWorkerSeconds: ONE_DAY,13 },14 }15...
Update the /api/
route to use the CACHE_ASSETS
constant.
1...2 .match('/api/:path*', ({ proxy, cache }) => {3 cache(CACHE_ASSETS)4 proxy('origin')5 })6...
We will now add a route that applies the same caching policy to all JavaScript (i.e., .js
and .mjs
) and CSS files.
1...2 // Cache stylesheets and scripts, but prevent browser caching3 .match(4 '/:path*/:file.:ext(js|mjs|css)',5 ({ cache, removeUpstreamResponseHeader, proxy, setResponseHeader }) => {6 setResponseHeader('cache-control', 'public, max-age=86400')7 removeUpstreamResponseHeader('set-cookie')8 cache(CACHE_ASSETS)9 proxy('origin')10 }11 )12...
The above route instructs Edgio to perform the following actions for all requests whose file extension matches js
, mjs
, or css
:
- Set the
cache-control
response header to:cache-control: public, max-age=86400
- Remove the
set-cookie
response header. Edgio will not cache a response when theset-cookie
response header is present. - Apply the caching policy defined by the
CACHE_ASSETS
constant. - Proxy these requests to your
origin
backend when we cannot serve them from cache.
Your routes.[js|ts]
should now look similar to the following:
1import {Router} from '@edgio/core/router';23const ONE_HOUR = 60 * 60;4const ONE_DAY = 24 * ONE_HOUR;5const CACHE_ASSETS = {6 edge: {7 maxAgeSeconds: ONE_DAY,8 staleWhileRevalidateSeconds: ONE_HOUR,9 },10 browser: {11 maxAgeSeconds: 0,12 serviceWorkerSeconds: ONE_DAY,13 },14};1516export default new Router()1718 // Here is an example where we cache api/* at the edge but prevent caching in the browser19 .match('/api/:path*', ({proxy, cache}) => {20 cache(CACHE_ASSETS);21 proxy('origin');22 })2324 // Cache stylesheets and scripts, but prevent browser caching25 .match(26 '/:path*/:file.:ext(js|mjs|css)',27 ({cache, removeUpstreamResponseHeader, proxy, setResponseHeader}) => {28 setResponseHeader('cache-control', 'public, max-age=86400');29 removeUpstreamResponseHeader('set-cookie');30 cache(CACHE_ASSETS);31 proxy('origin');32 }33 )3435 // send any unmatched request to origin36 .fallback(({proxy}) => proxy('origin'));
The final line in your routes.[js|ts]
defines a fallback()
method that proxies all requests that do not match a route to your origin
backend.
Testing Locally
You may run Edgio in local development mode to preview your website on your local machine prior to deployment. Local development mode allows for rapid development by allowing you to quickly test changes prior to deployment.
- From the command line or terminal, type
edgio dev
. - Preview your website by loading
https://127.0.0.1:3000
from within your preferred web browser.
Deploying Your Property
Evaluate site performance and QA functionality by deploying your property to Edgio. Run the following command from your property’s root directory:
1edgio deploy
Assess performance and caching behavior from the Edgio Developer console. Fine-tune your configuration by adding routes and then redeploying your property. Once you are ready to serve production traffic through Edgio, update your site’s DNS to point to our service.
Examples
Use our sample websites to gain hands-on experience on how to set up Edgio Performance. Specifically, you can browse our sample websites, view their source code, and even experiment on them by deploying them to Edgio.
Simple Example
This example demonstrates a basic Edgio configuration for publicdomainreview.org
. It contains two routes that cache content according to their file extension.
Full-Featured Example
This example demonstrates a full-featured Edgio configuration that showcases the following functionality:
-
Proxying requests to multiple origins
-
Increasing the cache buffer during revalidation through StaleWhileRevalidate
-
Prerendering pages and caching them to improve performance.
-
Instructing the browser to prefetch and deep fetch cached content to improve performance.
Prefetching only improves performance for cached content. Edgio returns
412 Precondition Failed
when prefetching a cache miss. This status code means that the prefetching did not occur for that request. -
Transforming the response through Serverless Compute
-
Generating performance insights through DevTools
-
Tracking Core Web Vitals through real user monitoring (RUM).
Issues?
If you have any issues during this process, check our forums for assistance.