Edgio

Traditional Sites

This guide describes how to get up and running with Edgio for traditional, multi-page applications. Edgio can enable traditional websites (e.g. jQuery, PHP, VanillaJS, etc.) to take advantage of the performance benefits of advanced caching and predictive prefetching. If your website is built on a modern framework such as React, Angular, or Vue, we recommend considering our framework-specific guides.
Note that the speed benefit for traditional sites from Edgio is dependent on the site’s JavaScript usage during the page load. If a page has JavaScript heavy processing during load it may reduce the benefit from Edgio. Contact your account manager or our sales department at 1 (866) 200 - 5463 to request site analysis prior to installation. Our typical turnaround time is 1 to 2 business days.

How Edgio for Traditional Sites Works

As shown below, Edgio becomes the main CDN for your site:
traffic
Requests for your site will now pass through Edgio’s globally distributed network of computers and then to your server. Your site’s main domain, such as www.site.com now points to Edgio, and your original server now responds to a new domain such as origin.site.com that Edgio will use for fetching your page data. Note that origin.site.com in this example is hidden from users; users continue to access your site transparently from your original domain www.site.com.
Edgio will do two things that accelerate your pages:
  • Globally distributed caching: Pages and content that are in Edgio cache will be returned to the user faster than being fetched from your server.
  • Predictive prefetching: Edgio predictively prefetch and serve data to the device before the user even requests it. By effectively streaming page data to the device a few seconds ahead of the shopper, the page load becomes instantaneous because there is no network to wait for. Normally the increased traffic from this kind of data streaming would overload your server, but Edgio’s caching layer acts as a “shield” to protect your origin for this load.

Implementation Process

The high level implementation process for Edgio is:
  1. Make sure your pages are cacheable
  2. Set up a project
  3. Configure caching and prefetching
  4. Test locally and on Edgio
  5. Go live by changing the DNS
We highly recommend performing this process on a staging server before attempting to try it on your production website.

Make Sure Your Pages are Cacheable

Edgio will only prefetch and accelerate pages that are cacheable, i.e. do not have user specific content. The good news is that most pages can be made cacheable with only a few adjustments. Let’s walk through an example.
Ecommerce homepage with a badge indicating the number of items in the cart
Consider the ecommerce page shown above. Most of the content on this page such as the main hero image, the menu items, the company logo, and more are not user specific. However, the badge indicating the number of items in the cart is specific to that user browsing the page. The cart count can’t be stored in the cache otherwise, every user would get a page with the same cart count. However to make this page cacheable we can simply remove the user specific parts and “late load” them with JavaScript. In this case, we could change the page so that the cart count is empty in the page HTML and let JavaScript on the page fetch the cart count and update the page HTML after it loads. This strategy of late load is fairly universal and you may want to delegate all the user specific content to a single late load request that is made by JavaScript on your page.
Here are some of common types of page content that may need this approach:
  • Badges indicating the number of items in cart or bag
  • Text or buttons dependent on the username or login status (e.g. “Login”, or “Welcome Bob”)
  • Segmented or personalized content such as recommended products based on the user’s profile or browsing behavior (note that recommended products based on page data are cacheable because the same recommended product would be shown to all users).
  • User specific parameters for analytics (e.g. if analytics tracks users by their userid or how frequently they visit the site).
See common things you need to look for on an eCommmerce site:
Non-cacheable contentHow to ChangeLocation
Cart item countLate load via APIGlobal
Welcome messageLate loadGlobal
Localized currencySplit cache based on cookieGlobal
Inline analyticsRefactorGlobal
Personalized bannersLate loadHomepage
Promo pricingLate loadPLP
Complex pricing (e.g. employee discounts, affiliate discounts, pricing based on item combinations or dollar amount in the cart)Late loadPLP, PDP
InventoryLower cache TTLPLP
Product recommendationsLate loadPDP
InventoryTargeted cache clearingPDP
Use this worksheet when auditing your site for personalized content to inventory and track the changes you will be making:
Edgio Origin Content Changes Worksheet

Prerequisites

Setup requires:

Install the Edgio CLI

If you have not already done so, install the Edgio CLI.
Bash
1npm i -g @edgio/cli@latest

Setup a Project

Create a project through the following command:
Bash
1npx @edgio/cli@latest init \
2 --edgioVersion latest \
3 --name <DOMAIN> \
4 --origin <DOMAIN>
Replace <DOMAIN> with your website’s domain when running the above command.
If asked by the CLI, choose Edgio Performance (CDN-as-Code) as the project type.
Once your project has been initialized, change into the directory of your project and run the following command to add the @edgio/starter connector:
Bash
1npm i -D @edgio/starter@latest
This connector will be used below for bundling and serving your site.

Project Structure

Before we get started, you should familiarize yourself with some of the key files in the Edgio project. We will create these files in a following step, but for now, here’s a quick overview of what they do:
  • routes.ts: This is automatically created during the init process and is where the routes to be cached and prefetched are defined, caching rules, as well as what to pass through without modification and what to serve up as static content.
  • src/service-worker.ts: Executed in the browser. The service worker is able to prefetch content (main product image, scripts, fonts, links, etc. as defined here) from within the potential next page’s document. We call this method “deep fetching”. This file is where deep-fetching rules are defined: the selector, how many elements, which attribute to fetch, resource type, and an optional callback function for more complex fetches (as shown in the example). Here’s more detailed info about deep fetching.
  • src/browser.ts: This is the entry point for the javascript bundle to be injected into the page. Logic for installing the service worker and other browser-specific functionality can be added here.
The routes.ts file is automatically created during the init process. You will need to create the src/service-worker.ts and src/browser.ts files under the src directory.

Configure Caching and Prefetching

Next we need to configure the caching in our newly created project. To do so, add a route for each URL you want to cache to the routes.ts file. For example, consider a site where the homepage (/), category pages (/category/xxxx), and product pages (/product/yyyy) are to be cached. Then your routes.ts file would look like:
JavaScriptroutes.ts
1import {Router} from '@edgio/core/router';
2
3export default new Router().get(
4 ['/collections/:path*', '/products/:path*', '/'],
5 {
6 caching: {
7 max_age: '1h',
8 service_worker_max_age: '1h',
9 bypass_client_cache: true,
10 },
11 headers: {
12 set_response_headers: {
13 'x-sw-cache-control': 'max-age=3600',
14 },
15 remove_origin_response_headers: ['set-cookie'],
16 },
17 origin: {
18 set_origin: 'origin',
19 },
20 }
21);
Refer to the guides on CDN-as-code and Caching for the full syntax to use in your routes.ts file.
In addition to configuring your caching in routes.ts as shown above, you may need to employ advanced prefetching techniques to achieve the best possible performance

Configure the Service Worker

To enable prefetching, your site’s service worker needs to use the @edgio/prefetch library’s Prefetcher class. If your site doesn’t currently have a service worker, one can easily be created using Google’s Workbox.
Here’s an example service worker based on Workbox:
JavaScriptsrc/service-worker.ts
1import {skipWaiting, clientsClaim} from 'workbox-core';
2import {precacheAndRoute} from 'workbox-precaching';
3import {Prefetcher} from '@edgio/prefetch/sw';
4
5skipWaiting();
6clientsClaim();
7precacheAndRoute(self.__WB_MANIFEST || []);
8
9new Prefetcher().route();

Serve the Service Worker

Within the Edgio router, we’ll need to serve the service-worker.ts file when requested by the browser. This can be accomplished automatically using the @edgio/starter connector installed in the earlier step

Using starterRoutes (Recommended)

By importing starterRoutes from @edgio/starter, the service-worker.ts file will be served automatically from the dist/service-worker.ts path. This is the recommended approach.
JavaScriptroutes.ts
1import {Router} from '@edgio/core/router';
2import shoppingFlowRouteFeatures from './shoppingFlowRouteFeatures';
3import {injectBrowserScript, starterRoutes} from '@edgio/starter';
4
5export default new Router()
6 .get(['/collections/:path*', '/products/:path*', '/'], {
7 caching: {
8 max_age: '1h',
9 service_worker_max_age: '1h',
10 bypass_client_cache: true,
11 },
12 headers: {
13 set_response_headers: {
14 'x-sw-cache-control': 'max-age=3600',
15 },
16 remove_origin_response_headers: ['set-cookie'],
17 },
18 origin: {
19 set_origin: 'origin',
20 },
21 })
22 .use(starterRoutes);

Install the Service Worker

Once you’ve created a service worker, code running in the browser window needs to register the service worker before prefetching can begin. To do this, we create a browser.ts file which will be injected into the page:
JavaScriptsrc/browser.ts
1import install from '@edgio/prefetch/window/install';
2import {prefetch} from '@edgio/prefetch/window/prefetch';
3
4document.addEventListener('DOMContentLoaded', () => {
5 install({
6 watch: [
7 {
8 selector: 'a[href^="/"]',
9 callback: (el) => {
10 prefetch(el.getAttribute('href'));
11 },
12 },
13 {
14 selector: 'link[href^="/"]',
15 callback: (el) => {
16 prefetch(el.getAttribute('href'));
17 },
18 },
19 ],
20 });
21});
In this file, we’re using the install function to register the service worker and the prefetch function to prefetch content. The install function takes an object with a watch property. The watch property is an array of objects that define what content to prefetch. In this example, we’re prefetching all links and stylesheets that start with a /.

Injecting browser.ts into the Response

Now that we’ve defined the client-side prefetch logic, we must inject the browser.ts file into the response. Injecting the script into the response allows for it to be executed in the browser once the response is received. To do this, we need to modify the router to transform the response we’ve received from the origin, add our browser script to the head of the document, and then send the modified response to the client.

Transforming the Response

To transform the origin response and inject the browser.ts file, we’ll use the transformResponse property on the proxy function. This function takes a callback function that receives the response from the origin and returns a modified response. We can then pass the response to the injectBrowserScript function to automatically add the browser.ts file to the head of the document.
JavaScriptroutes.ts
1import {Router} from '@edgio/core/router';
2import shoppingFlowRouteFeatures from './shoppingFlowRouteFeatures';
3import {injectBrowserScript, starterRoutes} from '@edgio/starter';
4
5export default new Router()
6 .get(['/collections/:path*', '/products/:path*', '/'], {
7 caching: {
8 max_age: '1h',
9 service_worker_max_age: '1h',
10 bypass_client_cache: true,
11 },
12 headers: {
13 set_response_headers: {
14 'x-sw-cache-control': 'max-age=3600',
15 },
16 remove_origin_response_headers: ['set-cookie'],
17 },
18 origin: {
19 set_origin: 'origin',
20 },
21 })
22 .get(['/collections/:path*', '/products/:path*', '/'], ({proxy}) => {
23 proxy('origin', {
24 transformResponse: (response) => {
25 injectBrowserScript(response);
26 },
27 });
28 })
29 .use(starterRoutes);

Understanding Caching and Prefetching

By injecting browser.ts into your app’s front-end code, your app will register the service worker and prefetch URLs that you have configured match a route configured with caching.max_age and caching.service_worker_max_age (in essence, when you configure a route to be cached, you are also declaring it to be a candidate for prefetching as well). Links that are visible when the page first loads are fetched immediately. Additional links will be fetched when the user scrolls down the page and more links become visible.
Prefetching can generate substantial additional network traffic. Edgio automatically shields your origin from this additional traffic by only serving prefetch requests from the edge cache. If a prefetch request cannot be served from the cache, Edgio will return an HTTP 412 status and the request will not be proxied to the origin. When this happens, the only effect for the user is that they will not see the speed benefit of prefetching. Therefore, the effectiveness of prefetching ramps up over time as users visit pages throughout your site. When the edge cache is cleared, either through the Edgio Console or automatically following a deployment, the speed benefit of prefetching is decreased until the cache fills up based on organic traffic.

Test Your Code Locally and on Edgio

Now that you’ve configured your caching in routes.ts, you should test it in your local development environment and on Edgio.

Running Locally

To test the caching behavior locally, run your project with the local cache option as shown below:
Bash
1edgio dev --cache

Running on Edgio

Now that you’re satisfied with your site in local development, it’s time to deploy it to the Edgio cloud. Once your code is deployed to the Edgio cloud, you can formally evaluate site performance and QA functionality.
Deploy the build to Edgio by running the edgio deploy command:
Bash
1edg deploy --organization=<ORGANIZATION>
Consult the Deployment guide for more information on the options for deploying your site.

Go Live by Changing the DNS

After you’ve configured and tested your site on Edgio, it’s time to take it live. At a high level, the process is:
  1. Specify the domain name of the site under the Configuration tab for the environment in the Edgio Console.
  2. Configure your SSL certificate under the Configuration tab for the environment in the Edgio Console.
  3. Create a CNAME record with your DNS provider with the value shown under the Domains section for the environment in the Edgio Console.
The third step (configuring your DNS) will be the crucial step that effectively transitions your domain to Edgio and should be done last.
Learn more.
Before going live, you should use the Edgio Onboarding Discovery Worksheet to help you think through common use cases and concerns and ensure a smooth launch.

Advanced Prefetching Techniques

An introduction to prefetching is available in the Prefetching guide. In addition, here are some techniques to take full advantage of the power of prefetching.

Deep Fetching

Deep fetching is an important technique for Edgio projects. By default, only HTML content is prefetched. In order to achieve truly instant page transitions, all of the assets needed to render the content that appears above the fold needs to be deep fetched. Refer to the Deep Fetching section of the Prefetching guide for more details on how to configure deep fetching in your project.

Prefetching based on Element Visibility

When installing the service worker, you can specify a watch list. Elements that match watch selectors can trigger a callback function when they become visible in the viewport:
JavaScript
1import {install, prefetch} from '@edgio/prefetch/window';
2
3document.addEventListener('DOMContentLoaded', function () {
4 install({
5 // If you don't have links specified with a `<a>` tags with `href` attributes, you can also
6 // specify watchers to prefetch when other elements are added to the page:
7 watch: [
8 {
9 selector: 'div.product-tile',
10 callback: (el) => {
11 const productId = el.getAttribute('data-product-id');
12 const catId = document
13 .getElementById('cat-listing')
14 .getAttribute('data-category-id');
15 prefetch(`/api/${catId}/${productId}`, 'fetch');
16 },
17 },
18 ],
19 });
20});

Maintenance

For the most part maintenance for traditional sites running on Edgio is minimal. However, the typical scenarios that require changes are:
  • If you add personalized or user-specific content to the page you will need to make sure it is late loaded as described in the Make sure your pages are cacheable section.
  • If you introduce a new segmentation of content (e.g. support a new language or currency), you may need to update your custom cache key.
  • If you change the layout of the page (especially above the fold), it may alter the assets you need to prefetch or deepfetch to achieve the best performance.