🎉 Introducing Edgio v6 which supports Node.js v16. Learn how to upgrade. 🎉
Edgio
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

Connector

This framework has a connector developed for Edgio. See Connectors for more information.

System Requirements

Sign up for Edgio

Deploying requires an account on Edgio. Sign up here for free.

Install the Edgio CLI

If you have not already done so, install the Edgio CLI.

Bash
1npm i -g @edgio/cli

Setup a Project

Create a project through the following command:

Bash
1npx @edgio/cli@latest init \
2 --name <DOMAIN> \
3 --environment default \
4 --origin <DOMAIN> \
5 --deploy

Replace <DOMAIN> with your website’s domain when running the above command.

If possible, try to run the above command from your website’s root directory.

Project Structure

Before we get started, you should familiarize yourself with some of the key files in the Edgio project:

  • service-worker.ts: Is run on 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 “deepfetching”. This file is where deepfetching 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 deepfetching.
  • shoppingFlowRouteHandler.ts: Is run on Edgio. It’s where the caching rules get implemented, as well as where the modifications to be made to the requests and/or responses to support caching of dynamic content are defined.
  • cache.ts: This is where the caching rules are defined for both Edgio (edge) and the browser.
  • routes.ts: This is where the routes to be cached and prefetched are defined, as well as what to pass through without modification and what to serve up as static content.
  • browser.ts: This is the entry point for the main.js javascript bundle which is added to the window.

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:

TypeScript
1// routes.ts
2import {Router} from '@edgio/core/router';
3import shoppingFlowRouteHandler from './shoppingFlowRouteHandler';
4
5export default new Router()
6 .get('/', shoppingFlowRouteHandler)
7 .get('/collections/*path', shoppingFlowRouteHandler)
8 .get('/products/*path', shoppingFlowRouteHandler);
TypeScript
1// shoppingFlowRouteHandler.ts
2import {CACHE_PAGES} from './cache';
3import {RouteHandler} from '@edgio/core/router/Router';
4
5const handler: RouteHandler = async ({cache, removeResponseHeader, proxy}) => {
6 cache(CACHE_PAGES);
7 removeUpstreamResponseHeader('set-cookie'); // The presence of a set-cookie header would prevent the response from being cached, so ensure set-cookie headers are removed.
8 proxy('origin');
9};
10
11export default handler;
TypeScript
1// cache.ts
2const ONE_HOUR = 60 * 60;
3const ONE_DAY = 24 * ONE_HOUR;
4const ONE_YEAR = 365 * ONE_DAY;
5
6/**
7 * The default cache setting for pages in the shopping flow
8 */
9export const CACHE_PAGES = {
10 edge: {
11 maxAgeSeconds: ONE_HOUR,
12 },
13 browser: {
14 maxAgeSeconds: 0,
15 serviceWorkerSeconds: ONE_HOUR,
16 },
17};

Refer to the guides on CDN-as-code and Caching for the full syntax to use in your routes.js 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

Understanding Caching and Prefetching

By injecting main.js into your app’s front-end code, your app will automatically prefetch all visible HTML links with URLs that match a route configured with edge.maxAgeSeconds and browser.serviceWorkerSeconds (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 Developer 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 Edgio Cloud. Once your code is deployed to 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 --team=<TEAM>

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 Developer console.
  2. Configure your SSL certificate under the Configuration tab for the environment in the Edgio Developer console.
  3. Create a CNAME record with your DNS provider with the value shown under the Domains section for the environment in the Edgio Developer console.

Each of these steps is described in more detail in the Domains guide. Note that third step (configuring your DNS) will be the crucial step that effectively transitions your domain to Edgio and should be done last.

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 POSTs

Most assets that need to be prefetched are HTTP GET requests. It is also possible to prefetch POST requests with some additional configuration.

When your app prefetches assets, the actual prefetch request is always a GET, so you need to make sure that your router is configured to respond to GET requests for any POST URL. In order to ensure that the response is cached as a POST by the service worker, you need to specify convertToGet: true in the cache config for the prefetch route handler, and to also use the transformMethod function to properly transform the GET request into a POST on the server:

JavaScript
1import {transformMethod} from '@edgio/core/transform';
2
3const postCacheConfig = {
4 edge: {
5 maxAgeSeconds: 60 * 60 * 24,
6 staleWhileRevalidateSeconds: 60 * 60,
7 },
8 browser: {
9 serviceWorkerSeconds: 60 * 60 * 24,
10 convertToGet: true,
11 },
12};
13
14export default new Router()
15 // When the request is a GET, convert it to post using serverless compute and cache the result
16 .get('/some-post-path', ({cache, proxy}) => {
17 cache(postCacheConfig);
18 proxy('origin', {
19 transformRequest: transformMethod('post'),
20 });
21 })
22 // When the request is a POST, forward it to origin from the edge without using serverless compute
23 .post('/some-post-path', ({cache, proxy}) => {
24 cache(postCacheConfig);
25 proxy('origin');
26 });

Prefetching based on Element Visibility

By default, <a> tags are watched by the Prefetcher so that the value of their href attributes are prefetched once the links become visible in the viewport. However, sometimes you might need to trigger a prefetch based on the visibility of other types of elements.

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.