简体   繁体   中英

CDN Fallback for Dependant Scripts

If I am using the following scripts:

  • jQuery
  • jQuery Validation
  • jQuery Validation Unobtrusive
  • Bootstrap

Bootstrap and jQuery Validation require jQuery and jQuery Validation Unobtrusive requires jQuery Validation so we have interdependent scripts. The fallback scripts I have seen all look something like this:

(window.jQuery || document.write('<script src="/bundles/jquery"><\/script>'));
($.validator || document.write('<script src="/bundles/jqueryval"><\/script>'));
($.validator.unobtrusive || document.write('<script src="/bundles/jqueryvalunobtrusive"><\/script>'));
($.fn.modal || document.write('<script src="/bundles/bootstrap"><\/script>'));

The problem is that if I am using the ajax.aspnetcdn.com CDN and it fails, then the first line will cause jQuery to be loaded locally but the next three lines of code will execute before that and error because $ is undefined.

Is there a standard way to handle these types of interdependent fall-back scripts? I have looked around and can't find a resource for handling this type of scenario.

UPDATE

I answered the question as best I can but I'm still looking for an answer on how people handle this.

It seems overkill to rely on yet another third party script but I have discovered Fallback.js and YepNope.js which may be able to handle this scenario. I am not sure about the performance implications of the everyday scenario where the CDN's just work. More info here .

I also had a go at writing my own implementations:

JavaScript Fallbacks

(function (document, fallbacks) {

    var check = function (fallbacks, i) {
        if (i < fallbacks.length) {
            var fallback = fallbacks[i];
            if (fallback.test()) {
                check(fallbacks, i + 1);
            }
            else {
                var script = document.createElement("script");
                script.onload = function () {
                    check(fallbacks, i + 1);
                };
                script.src = fallback.src;
                document.getElementsByTagName("body")[0].appendChild(script);
            }
        }
    }
    check(fallbacks, 0);

})(document, [
    { test: function () { return window.Modernizr; }, src: "/js/modernizr.js" },
    { test: function () { return window.jQuery; }, src: "/js/jquery.js" },
    { test: function () { return $.validator; }, src: "/js/jquery-validate.js" },
    { test: function () { return $.validator.unobtrusive; }, src: "/js/jquery-validate-unobtrusive.js" },
    { test: function () { return $.fn.modal; }, src: "/js/bootstrap.js" },
    { test: function () { return window.Hammer && window.Hammer.VERSION; }, src: "/js/hammer.js" },
    { test: function () { return window.Zepto; }, src: "/js/bootstrap-touch-carousel.js" }
]);

CSS Fallbacks

The idea for using a meta tag was 'borrowed' from the new ASP.NET 5 MVC 6 framework.

(function (document, fallbacks) {

    var metas = document.getElementsByTagName("meta");

    for (var i = 0; i < fallbacks.length; ++i) {
        var fallback = fallbacks[i];

        for (j = 0; j < metas.length; ++j) {
            var meta = metas[j];
            if (meta.getAttribute("name") == fallback.metaName) {
                if (!fallback.test(meta)) {
                    var link = document.createElement("link");
                    link.href = fallback.href;
                    link.rel = "stylesheet";
                    document.getElementsByTagName("head")[0].appendChild(link);
                }
                break;
            }
        }

    }

})(document, [
    {
        // metaName - The name of the meta tag that the test is performed on. The meta tag must have a class from the
        //            relevant stylesheet on it so it is styled and a test can be performed against it. E.g. for 
        //            font awesome the <meta name="x-font-awesome-stylesheet-fallback-test" class="fa"> meta tag is
        //            added. The 'fa' class causes the font awesome style to be applied to it.
        metaName: "x-font-awesome-stylesheet-fallback-test",
        // test - The test to perform against the meta tag. Checks to see if the Font awesome styles loaded 
        //        successfully by checking that the font-family of the meta tag is 'FontAwesome'.
        test: function (meta) { return meta.style.fontFamily === "FontAwesome"; },
        // href - The URL to the fallback stylesheet.
        href: "/css/font-awesome.css"
    }
]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM