🎉 Introducing Edgio v6 which supports Node.js v16. Learn how to upgrade. 🎉
Edgio
Edgio

Getting Started with CDN-As-Code

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:

  1. Creating and deploying a property to Edgio.

    Learn more.

    Alternatively, you may experiment with our sample websites by deploying them to Edgio.

  2. 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:

    Bash
    1npx @edgio/cli@latest init \
    2--name <PROPERTY> \
    3--deploy
  3. Define routes that determine how Edgio will handle that traffic.

  4. Test your changes locally.

  5. 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:

JavaScript./routes.js
1import {Router} from '@edgio/core/router';
2
3// const ONE_HOUR = 60 * 60
4// const ONE_DAY = 24 * ONE_HOUR
5
6export default new Router()
7
8 // Here is an example where we cache api/* at the edge but prevent caching in the browser
9 // .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 // })
22
23 // send any unmatched request to origin
24 .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:

    JavaScript
    1.match('/:path*', () => {
    2 // route handler goes here
    3})
  • Match all GET requests whose URL path starts with /marketing/images/:

    JavaScript
    1.get('/marketing/images/:path*', () => {
    2 // route handler goes here
    3})
  • Match all GET and POST requests whose URL path starts with /marketing/images/ and contain the sport request header set to basketball:

    JavaScript
    1.match(
    2 {
    3 path: '/marketing/images/:path*',
    4 method: /GET|POST/i, // regular expression
    5 headers: { 'sport': /^basketball$/i }, // keys are header names; values are regular expressions
    6 },
    7 () => {
    8 // route handler goes here
    9})

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:
    JavaScript
    1.match('/:path*', ({ proxy, cache }) => {
    2 cache({
    3 edge: {
    4 maxAgeSeconds: 3600
    5 }
    6 })
    7 proxy('origin')
    8})
  • Set the images response header and proxy cache misses to the origin backend for all GET requests whose URL path starts with /marketing/images/:
    JavaScript
    1.get('/marketing/images/:path*', ({ setResponseHeader, proxy }) => {
    2 setResponseHeader('images', 'true')
    3 proxy('origin')
    4})

View additional examples.

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:

JavaScript./routes.js
1import {Router} from '@edgio/core/router';
2
3const ONE_HOUR = 60 * 60;
4const ONE_DAY = 24 * ONE_HOUR;
5
6export default new Router()
7
8 // Here is an example where we cache api/* at the edge but prevent caching in the browser
9 .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 })
22
23 // send any unmatched request to origin
24 .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.

JavaScript./routes.js
1import { Router } from '@edgio/core/router'
2
3 const ONE_HOUR = 60 * 60
4 const ONE_DAY = 24 * ONE_HOUR
5 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.

JavaScript./routes.js
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.

JavaScript./routes.js
1...
2 // Cache stylesheets and scripts, but prevent browser caching
3 .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 the set-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:

JavaScript./routes.js
1import {Router} from '@edgio/core/router';
2
3const 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};
15
16export default new Router()
17
18 // Here is an example where we cache api/* at the edge but prevent caching in the browser
19 .match('/api/:path*', ({proxy, cache}) => {
20 cache(CACHE_ASSETS);
21 proxy('origin');
22 })
23
24 // Cache stylesheets and scripts, but prevent browser caching
25 .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 )
34
35 // send any unmatched request to origin
36 .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.

  1. From the command line or terminal, type edgio dev.
  2. 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:

Bash
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.

Learn more.

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:

Issues?

If you have any issues during this process, check our forums for assistance.