什么是一个好方法来尝试加载托管的jQuery在谷歌(或其他谷歌托管库),但加载我的jQuery副本,如果谷歌尝试失败?

我不是说谷歌很古怪。在某些情况下,谷歌副本会被屏蔽(例如,显然在伊朗)。

我是否会设置一个计时器并检查jQuery对象?

两份拷贝都通过的危险是什么?

并不是真的在寻找像“只用谷歌”或“只用你自己的”这样的答案。我理解这些论点。我还知道用户可能缓存了谷歌版本。我在考虑云计算的后备方案。


编辑:这部分增加了…

因为谷歌建议使用谷歌。加载加载ajax库,它执行回调时,我想知道这是否是序列化这个问题的关键。

我知道这听起来有点疯狂。我只是想弄清楚它是否能以一种可靠的方式完成。


更新:jQuery现在托管在微软的CDN上。

http://www.asp.net/ajax/cdn/


当前回答

更新: 这个答案原来是错的。真正的解释请看评论。


你们的问题大部分都已经回答了,但至于最后一部分

两份拷贝都通过的危险是什么?

没有一个真的。你会浪费带宽,下载第二个无用的副本可能会增加几毫秒的时间,但如果它们都通过了,也不会造成实际伤害。当然,您应该使用上面提到的技术来避免这种情况。

其他回答

我做了一个Gist,如果还没有加载jQuery,它应该动态加载,如果源代码失败,它将继续执行回退(从许多答案拼接在一起):https://gist.github.com/tigerhawkvok/9673154

请注意,我计划保持更新主旨,但不是这个答案,因为它是值得的!

/* See https://gist.github.com/tigerhawkvok/9673154 for the latest version */
function cascadeJQLoad(i) { // Use alternate CDNs where appropriate to load jQuery
    if (typeof(i) != "number") i = 0;
    // the actual paths to your jQuery CDNs
    var jq_paths = [
        "ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js",
        "ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.0.min.js"
    ];
    // Paths to your libraries that require jQuery
    var dependent_libraries = [
        "js/c.js"
    ];
    if (window.jQuery === undefined && i < jq_paths.length) {
        i++;
        loadJQ(jq_paths[i], i, dependent_libraries);
    }
    if (window.jQuery === undefined && i == jq_paths.length) {
        // jQuery failed to load
        // Insert your handler here
    }
}

/***
 * You shouldn't have to modify anything below here
 ***/

function loadJQ(jq_path, i, libs) { //load jQuery if it isn't already
    if (typeof(jq_path) == "undefined") return false;
    if (typeof(i) != "number") i = 1;
    var loadNextJQ = function() {
        var src = 'https:' == location.protocol ? 'https' : 'http';
        var script_url = src + '://' + jq_path;
        loadJS(script_url, function() {
            if (window.jQuery === undefined) cascadeJQLoad(i);
        });
    }
    window.onload = function() {
        if (window.jQuery === undefined) loadNextJQ();
        else {
            // Load libraries that rely on jQuery
            if (typeof(libs) == "object") {
                $.each(libs, function() {
                    loadJS(this.toString());
                });
            }
        }
    }
    if (i > 0) loadNextJQ();
}

function loadJS(src, callback) {
    var s = document.createElement('script');
    s.src = src;
    s.async = true;
    s.onreadystatechange = s.onload = function() {
        var state = s.readyState;
        try {
            if (!callback.done && (!state || /loaded|complete/.test(state))) {
                callback.done = true;
                callback();
            }
        } catch (e) {
            // do nothing, no callback function passed
        }
    };
    s.onerror = function() {
        try {
            if (!callback.done) {
                callback.done = true;
                callback();
            }
        } catch (e) {
            // do nothing, no callback function passed
        }
    }
    document.getElementsByTagName('head')[0].appendChild(s);
}

/*
 * The part that actually calls above
 */

if (window.readyState) { //older microsoft browsers
    window.onreadystatechange = function() {
        if (this.readyState == 'complete' || this.readyState == 'loaded') {
            cascadeJQLoad();
        }
    }
} else { //modern browsers
    cascadeJQLoad();
}

谷歌托管jQuery

如果你关心旧的浏览器,主要是IE9之前的IE版本,这是最广泛兼容的jQuery版本

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>

如果你不关心老die,这个更小更快:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

备份/后备计划!

无论哪种方式,您都应该使用回退到本地,以防谷歌CDN失败(不太可能)或在您的用户访问您的网站的位置被阻止(略有可能),如伊朗或有时中国。

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>if (!window.jQuery) { document.write('<script src="/path/to/your/jquery"><\/script>'); }
</script>

参考:http://websitespeedoptimizations.com/ContentDeliveryNetworkPost.aspx

对于那些使用ASP的人。在你的BundleConfig.cs中添加以下代码来启用jquery的CDN:

bundles.UseCdn = true;
Bundle jqueryBundle = new ScriptBundle("~/bundles/jquery", "//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js").Include("~/Scripts/jquery-{version}.js");
jqueryBundle.CdnFallbackExpression = "window.jQuery";
bundles.Add(jqueryBundle);

虽然编写document.write("<script></script>")对于jQuery来说似乎更容易退出,但Chrome在这种情况下给出了验证错误。所以我更喜欢打破“剧本”这个词。所以它变得像上面一样安全。

<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.11.1.min.js"></script>
<script>if (typeof jQuery === "undefined") {
   window.jqFallback = true;
   document.write("<scr"+"ipt src='http://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.1/jquery.min.js'></scr"+"ipt>");
} </script>

对于长期的问题,最好记录JQuery的回退。在上面的代码中,如果第一个CDN不可用,则从另一个CDN加载JQuery。但是你可能想要知道错误的CDN并永久删除它。(这种情况是非常特殊的情况)此外,最好记录回退问题。所以你可以用AJAX发送错误案例。因为JQuery没有定义,所以对于AJAX请求应该使用普通的javascript。

<script type="text/javascript">
    if (typeof jQuery === 'undefined' || window.jqFallback == true) {
        // XMLHttpRequest for IE7+, Firefox, Chrome, Opera, Safari
        // ActiveXObject for IE6, IE5
        var xmlhttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
        var url = window.jqFallback == true ? "/yourUrl/" : "/yourUrl2/";
        xmlhttp.open("POST", url, true);
        xmlhttp.send();
    }
</script>

如果你的网站上嵌入了modernizr.js,你可以使用内置的yepnope.js来异步加载你的脚本——其中包括jQuery(带备份)。

Modernizr.load([{
    load : '//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js'
},{
    test : window.jQuery,
    nope : 'path/to/local/jquery-1.7.2.min.js',
    both : ['myscript.js', 'another-script.js'],
    complete : function () {
        MyApp.init();
    }
}]);

这将从Google-cdn加载jQuery。然后检查jQuery是否加载成功。如果不是("nope"),则加载本地版本。同时也加载了您的个人脚本——“both”表示加载过程的初始化独立于测试的结果。

当所有加载过程完成时,执行一个函数,在这种情况下为'MyApp.init'。

我个人更喜欢这种异步脚本加载方式。由于我在构建网站时依赖modernizr提供的功能测试,所以我将它嵌入到网站中。所以实际上没有开销。