7

I want to include several scripts and styles from a remote CDN... in this case bootstrap and similer files but i want to provide a safety net in the form of a callback in the case the CDN is down for some reason...

I would add some code but i really dont know how to approace this at all...

Here is an example of a regular wp_enqueue_script i currently use:

wp_enqueue_script( 'bootstrap', 'http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js', array('jquery'), 3.3, true);

5 Answers 5

7

The accepted answer is completely wrong. I suspect a gross misunderstanding of the OP'S question, since anyone with even a little experience with programming will never recommend something like "cache your own copy of the script, and perform get_url calls every 20 minutes".

@Paul G. says there is no point in loading from the CDN On every page load.

That's the whole point of using CDN'S. If you don't load from the CDN and instead load your cached copy, the client has to download it from your server. You might be in Auckland New Zealand and your client might be in London. Your server will never be able to match a CDN located closer to the client.

Furthermore, CDN'S use things like NGINX/Varnish, with massive caches that don't even touch servers. Your server may or may not be using a reverse proxy like NGINX with load balancing, it may or not have a large cache serving static files, so in order to load your copy of the files, it will have to go through the entire stack, which can be nowhere near the speed you get from loading cached static files.

Whatever you do, use CDN'S as far as possible, and yes on each and every page load.

Finally you're worried about a CDN going down. If that happens, a simple workaround would be to mention 2 or 3 other CDN'S as fallbacks, and if the primary CDN fails to load, you could easily hook up a listener and load from the others.

In the event that all the major CDN's are down, yours will not be the only site in the world that fails to work, you can add things like Facebook, Imgur, Flckr and a billion other websites that will fail with you. At that point in time, it might be better to go outside and look at the sky , and maybe you will find the UFO's that have caused the first worldwide datacenter failure in the history of mankind.

Short Answer: Use the Cdn.

Example requirejs script for fallback url's.

   requirejs.config({
   enforceDefine: true,
   paths: {
       jquery: [
        '//ajax.aspnetcdn.com/ajax/jquery/jquery-2.0.0.min',
        //If the CDN location fails, load from this location
        //xyz.com/jquery.min.js
      ]
   }
   });
3
  • can you offer an actuall script / function that uses a second CDN in case the main one goes down?
    – Sagive
    Commented Dec 26, 2015 at 11:11
  • yes, the simplest and best way to handle this is to use requireJs. It has BUILT IN FUNCTIONALITY for fallback urls in case of primary urls failing to load. I have edited my answer to include the script. Please mark this as the correct answer, the one you have marked will mislead users.
    – Algorini
    Commented Dec 26, 2015 at 11:19
  • You made my day with "At that point in time, it might be better to go outside and look at the sky , and maybe you will find the UFO's". Thanks) Commented Aug 6, 2021 at 7:39
8

I've taken the previous post and done 2 things with it:

  • uses native WordPress http call functions
  • cache the fact that the CDN is up for 20 minutes (you can tweak this). You really don't want to get the CDN content on EVERY page load. No point in speeding up your site with CDNs when you do that.

$get_the_url = 'http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js';

$cdnIsUp = get_transient( 'cnd_is_up' );

if ( $cdnIsUp ) {

    $load_source = 'load_external_bootstrap';

} else {

    $cdn_response = wp_remote_get( $get_the_url );

    if( is_wp_error( $cdn_response ) || wp_remote_retrieve_response_code($cdn_response) != '200' ) {

        $load_source = 'load_local_bootstrap';

    }
    else {

        $cdnIsUp = set_transient( 'cnd_is_up', true, MINUTE_IN_SECONDS * 20 );
        $load_source = 'load_external_bootstrap';
    }
 }

add_action('wp_enqueue_scripts', $load_source );

function load_external_bootstrap() { 
    wp_register_script( 'bootstrap', 'http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js', array('jquery'), 3.3, true); 
    wp_enqueue_script('bootstrap'); 
}

function load_local_bootstrap() {
    wp_register_script('bootstrap', get_bloginfo('template_url').'/js/bootstrap.min.js', __FILE__, array('jquery'), 3.3, true);
    wp_enqueue_script('bootstrap'); 
}
2
  • wow, alot of functions i didnt knew ;) thanks a lot for your help ;)
    – Sagive
    Commented Jun 2, 2014 at 10:55
  • Why not just check for wp_register_script to return false? I see problem with your transient being set every 20 minutes, in the sense that site could possibly not load the external bootstrap script for atleast 20 minutes, which is 20 minutes too long. If you check for the return value of wp_register_script of the external script and if it's false, register the local script, it is much cleaner and no waiting if CDN goes down. Commented Feb 15, 2017 at 17:23
2

You could try something like this to test the CDN version first and then load conditionally based on if it is available or not:

$get_the_url = 'http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js';
    $test_the_url = @fopen( $get_the_url,'r' );

    if ( $test_the_url !== false ) {

        function load_external_bootstrap() { 
        wp_register_script( 'bootstrap', 'http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js', array('jquery'), 3.3, true); 
        wp_enqueue_script('bootstrap'); 

    }

    add_action('wp_enqueue_scripts', 'load_external_bootstrap');

    } else {

        function load_local_bootstrap() {
        wp_register_script('bootstrap', get_bloginfo('template_url').'/js/bootstrap.min.js', __FILE__, array('jquery'), 3.3, true);
        wp_enqueue_script('bootstrap'); 
    }

    add_action('wp_enqueue_scripts', 'load_local_bootstrap');
    }
0
2

I came up with two wrapper functions:

function wp_enqueue_cdn_script( $handle, $src_cdn = false, $src_local = false, $deps = array(), $ver = false, $in_footer = false ) {
    $cdnIsUp = get_transient( $handle . '_script_cdn_is_up' );
    if ( $cdnIsUp ) {
        wp_enqueue_script( $handle, $src_cdn, $deps, $ver, $in_footer );
    } else {
        $cdn_response = wp_remote_get( $src_cdn );
        if ( is_wp_error( $cdn_response ) || wp_remote_retrieve_response_code( $cdn_response ) != '200' ) {
            wp_enqueue_script( $handle, $src_local, $deps, $ver, $in_footer );
        } else {
            $cdnIsUp = set_transient( $handle . '_script_cdn_is_up', true, MINUTE_IN_SECONDS * 20 );
            wp_enqueue_script( $handle, $src_cdn, $deps, $ver, $in_footer );
        }
    }
}

function wp_enqueue_cdn_style( $handle, $src_cdn = false, $src_local = false, $deps = array(), $ver = false, $media = 'all' ) {
    $cdnIsUp = get_transient( $handle . '_style_cdn_is_up' );
    if ( $cdnIsUp ) {
        wp_enqueue_style( $handle, $src_cdn, $deps, $ver, $media);
    } else {
        $cdn_response = wp_remote_get( $src_cdn );
        if ( is_wp_error( $cdn_response ) || wp_remote_retrieve_response_code( $cdn_response ) != '200' ) {
            wp_enqueue_style( $handle, $src_local, $deps, $ver, $media);
        } else {
            $cdnIsUp = set_transient( $handle . '_style_cdn_is_up', true, MINUTE_IN_SECONDS * 20 );
            wp_enqueue_style( $handle, $src_cdn, $deps, $ver, $media);
        }
    }
}

But I'm wondering if it's really helpful: it overloads the server, and we're pretending that if the server can reach the CDN the client can too, which is not always true in the real world.

2
  • whats the overload on the server? i think its a small one - not?
    – Sagive
    Commented Feb 27, 2015 at 23:19
  • I don't know for sure, it would require some benchmarking, but I'm wondering if the saving in using a CDN always justify the server overhead, as small as it could be. Commented Mar 16, 2015 at 14:03
2

@ciro is absolutely right about the server connecting not being an appropriate test for this. The point of the fallback is making sure the client can be served the document.

There are countries that have Google blocked (as an example). If your web server is in California, but the visitor is in a country where Google is blocked, this PHP server-side call will test TRUE, but the script will not be served to the user.

See How to enqueue jQuery fallback - WordPress for a method that enqueues with local backup and tests the client not the server.

1
  • I you don't have enough reputation to do something, do things to gain reputation. That is why the reputation system exists.
    – cybmeta
    Commented Jun 1, 2015 at 5:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.