使用Google託管的jQuery的最佳方法,但在Google上回退到我的託管庫失敗


Answers

迄今為止最簡單和最乾淨的方法:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="path/to/your/jquery"><\/script>')</script>
Question

嘗試在Google (或其他Google託管庫)上加載託管jQuery的好方法是什麼,但是如果Google嘗試失敗,請加載我的jQuery副本?

我不是說谷歌很脆弱。 有些情況下,谷歌的副本被阻止(例如顯然在伊朗)。

我會設置一個計時器並檢查jQuery對象嗎?

這兩個副本都會遇到什麼危險?

不是真的在尋找像“只使用Google的”或“只使用你自己的”的答案。 我理解這些論點。 我也明白,用戶可能會緩存Google版本。 我一般在考慮雲的回退。

編輯:這部分添加...

由於Google建議使用google.load加載ajax庫,並且在完成時執行回調,所以我想知道這是否是序列化此問題的關鍵。

我知道這聽起來有點瘋狂。 我只是想弄清楚它是否可以以可靠的方式完成。

更新:現在託管在微軟CDN上的jQuery。

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




if (typeof jQuery == 'undefined')) { ...

要么

if(!window.jQuery){

如果cdn版本未加載,將不起作用,因為瀏覽器將運行這個條件,並且在它仍然下載需要jQuery的其餘javascript,並且它返回錯誤。 解決方案是通過該條件加載腳本。

    <script src="http://WRONGPATH.code.jquery.com/jquery-1.4.2.min.js" type="text/javascript"></script><!--  WRONGPATH for test-->
  <script type="text/javascript">
  function loadCDN_or_local(){
    if(!window.jQuery){//jQuery not loaded, take a local copy of jQuery and then my scripts
      var scripts=['local_copy_jquery.js','my_javascripts.js'];
      for(var i=0;i<scripts.length;i++){
      scri=document.getElementsByTagName('head')[0].appendChild(document.createElement('script'));
      scri.type='text/javascript';
      scri.src=scripts[i];
    }
  }
  else{// jQuery loaded can load my scripts
    var s=document.getElementsByTagName('head')[0].appendChild(document.createElement('script'));
    s.type='text/javascript';
    s.src='my_javascripts.js';
  }
  }
  window.onload=function(){loadCDN_or_local();};
  </script>






我做了一個Gist,它應該動態加載jQuery,如果它尚未加載,並且源代碼失敗,它會繼續回退(從許多答案縫合在一起): https://gist.github.com/tigerhawkvok/9673154https://gist.github.com/tigerhawkvok/9673154

請注意我打算更新Gist,但不會回答這個問題,因為它是值得的!

/* 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();
}



如果您的網站上嵌入了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”),則加載本地版本。 此外,您的個人腳本也被加載 - “兩個”表示加載過程獨立於測試結果而被引入。

當所有加載過程完成時,執行一個函數,如果是'MyApp.init'。

我個人更喜歡這種異步腳本加載方式。 由於我在構建網站時依靠modernizr提供的功能測試,因此無論如何我都將其嵌入網站中。 所以實際上沒有開銷。




對於那些使用ASP.NET MVC 5的人來說,將這些代碼添加到你的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);



這裡有一些很棒的解決方案,但我想就本地文件進一步研究。

在Google確實失敗的情況下,它應該加載本地源,但是服務器上的物理文件可能不一定是最好的選擇。 我提出這個問題是因為我目前正在實現相同的解決方案,只是我想回退到由數據源生成的本地文件。

我之所以這樣做,是因為我想要記住從Google加載的內容與我在本地服務器上加載的內容。 如果我想更改版本,我想讓我的本地副本與我試圖從Google加載的內容同步。 在有許多開發人員的環境中,我認為最好的方法是自動執行此過程,以便所有人都必須在配置文件中更改版本號。

這是我提出的理論解決方案:

  • 在應用程序配置文件中,我將存儲3件事:庫的絕對URL,JavaScript API的URL和版本號
  • 編寫一個獲取庫自身文件內容的類(從app config獲取URL),將它存儲在我的數據源中,其名稱和版本號
  • 編寫一個處理程序,將本地文件從數據庫中提取出來並緩存文件,直到版本號更改。
  • 如果它改變了(在我的應用程序配置中),我的課程將根據版本號提取文件內容,將它保存為數據源中的新記錄,然後處理程序將啟動並提供新版本。

從理論上講,如果我的代碼編寫得當,我所需要做的就是在我的應用程序配置中更改版本號,然後中提琴! 您有一個自動回退解決方案,您不必在服務器上維護物理文件。

大家怎麼想? 也許這是矯枉過正,但它可能是一個維護你的AJAX庫的優雅方法。

橡子







有條件地加載最新/傳統的jQuery版本和後備:

<!--[if lt IE 9]>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="/public/vendor/jquery-legacy/dist/jquery.min.js">\x3C/script>')</script>
<![endif]-->
<!--[if gte IE 9]><!-->
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="/public/vendor/jquery/dist/jquery.min.js">\x3C/script>')</script>
<!--<![endif]-->



谷歌託管jQuery

  • 如果您關心的是舊版瀏覽器,主要是IE9之前的IE版本,這是最廣泛兼容的jQuery版本
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
  • 如果你不關心oldIE,這個更小更快:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

備份/回退計劃!

  • 無論採用哪種方式,只要Google 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 : http://websitespeedoptimizations.com/ContentDeliveryNetworkPost.aspx




Links