CDN Fallbacks in Web Development

Rather than loading static resources locally such as CSS and JS, a lot of developers often include the resources via a CDN to improve website performance. However, there may be occasions where the CDNs experience downtime which can result in many websites breaking. CDN fallbacks in web development should be considered and factored into any website.

A simple example of using code to provide a CDN fallback can be described below.

A document includes the jQuery library from Google’s CDN and contains code below to check if window.jQuery exists, and if it doesn’t, write out the jQuery include from your local directory.

<!DOCTYPE html>
<html>
<head>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script>
        window.jQuery || document.write('<script src="/path/to/your/jquery"></script>');
    </script>
</head>
<body>
</body>
</html>

This provides a good failsafe if Google’s hosted jQuery file cannot be retrieved.

You can do similar checks with other JavaScript libraries. For Twitter Bootstrap, you can check if one of Bootstrap’s plugins is defined to check if the CDN has retrieved the library.

<!-- Bootstrap JS CDN -->
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>

<script>if(typeof($.fn.modal) === 'undefined') {document.write('<script src="/local/bootstrap.min.js"></script>')}</script>

This can get quite messy if you have multiple libraries being requested from CDNs and are providing checks for each of them.

There are JavaScript libraries that provide code to handle fallbacks, such as YepNopeJS and FallbackJS.

YepNopeJS has been deprecated as of 2015, however FallbackJS is still active and widely used, and you can use the load method of the fallback object.

For example, the code below provides a list of potential URLs FallbackJS can use to load jQuery.

fallback.load({
    jQuery: [
        '//ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js',
        '//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.0/jquery.min.js'
        '/js/jquery-3.2.1.min.js'
    ]
});

To test out this scenario, you can deliberately make the library on the first line fail by changing the URL. Doing this will mean that jQuery will be loaded from the second line (Cloudflare) instead!

fallback.load({
    jQuery: [
        '//ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.fail-on-purpose.js',
        '//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.0/jquery.min.js'
        '/js/jquery-3.2.1.min.js'
    ]
});