2012-08-22 66 views
29

在我的主幹應用程序中,我需要爲每個需要的文件提供回退,以防發送CDN失敗。RequireJS:如果CDN失敗,本地回退

我試圖重寫require.onError像這樣:

require.onError = function (err) { 
    if (err.requireType === 'timeout') { 
     var url = err.requireModules; 

     if (!!~url.indexOf("jquery/")) 
      console.warn("CDN timed out, falling back to local jQuery.js") 
      require(["libs/jquery"]); 
      return; 
     if (!!~url.indexOf("jqueryui/")) 
      console.warn("CDN timed out, falling back to local jQueryUI.js") 
      require(["libs/jqueryui"]); 
      return; 
     if (!!~url.indexOf("underscore")) 
      console.warn("CDN timed out, falling back to local underscore.js") 
      require(["libs/underscore"]); 
      return; 
     if (!!~url.indexOf("backbone")) 
      console.warn("CDN timed out, falling back to local backbone.js") 
      require(["libs/backbone"]); 
      return; 
    } 
} 

的問題是,這將異步加載的後備文件。我需要按順序加載這些文件,就像原始的require語句一樣,我使用order!插件。

隨着覆蓋onError:當CDN加載失敗時,回退加載開始,但不等待。這提出了一個問題,因爲腳本被命令根據它們的依賴性加載。下面來看看在我原來的require聲明,依賴於CDN:

require([ 
    "order!http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js", 
    "order!http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js", 
    "order!http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.3/underscore-min.js", 
    "order!http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js", 
    "order!utils/date", 
    "order!core/core", 
    "order!core/errors", 
    "order!core/constants" 
], function() { 
    ... 
} 
+0

兩者CDN的並不可怕,他們平均只有失敗,每天一次,最多約一分鐘的窗口,都是免費的。無論如何,我覺得這是一個有待解決的有趣問題。即使您擁有完美的CDN,始終保持良好的後備效果,以保持用戶體驗。你能建議其他CDN嗎? – Austin

+0

我明白你來自哪裏,但是我沒有建議爲我們公司購買這樣的東西,但沒有提供足夠的證據證明我已經嘗試了一切,以使當前的系統正常工作。另外,我對任何編程專長都很感興趣,我可以看到這個特定的解決方案對很多人都有用,因爲許多開發者(特別是自由職業者)不使用付費CDN。 – Austin

+1

CDN現在真實便宜(每月$ 2到$ 3)...我使用AccuWebHosting.Com CDN,從未經歷過任何停機。那麼,如果一臺服務器在CDN上失敗了,內容會立即從最接近的可用下一個POP發出......而且通常有40到50個POP在一個好的CDN中...... –

回答

57

您正在使用什麼版本RequireJS的?看起來你可能想要將jQuery的fallback配置爲配置中的路徑,然後將jQuery設置爲對其他需要它的模塊的依賴。如果你使用〜> 2.0,像(未經測試):

// in your requirejs config 
requirejs.config({ 
    //To get timely, correct error triggers in IE, force a define/shim exports 
    // check. 
    enforceDefine: true, 
    paths: { 
     jquery: [ 
      'http://somecdn.com/jquery.min', // your cdn 
      'lib/jquery' // your fallback 
     ], 
     jqueryui: "http://somecdn.com/jquery-ui.min.js" 
    }, 
    shim: { 
     jqueryui: ['jquery'] 
    } 
}); 

// then in your requires 
require([jquery, jqueryui, foo, bar], function($) { 
    // stuff 
}); 

他們談論如何做到這一點in the wiki。如果你沒有使用v2.x,那麼在這裏也有一種處理方法。

如果將所有模塊配置爲指定自己的依賴關係,則不需要擔心order!指令。

+0

打了2分鐘我的帖子,但是,這是我一起去的答案。 – Austin

+0

哈哈沒有。我認爲這是大約15秒。 – numbers1311407

+2

運行優化程序後,如何進行管理?它是否將腳本標籤添加到排除文件的HTML? – sidonaldson

19

我找到了RequireJS 2.x.x中提供的問題的解決方案。需要這種解決方案,因此RequireJS在其配置中添加了一個paths對象。這爲CDN提供備用功能,如果它們失敗。

還應該注意的是,order!插件在Require 2.0中已被棄用,所以我還需要使用shim對象來定義依賴關係。這實際上是一個非常有趣的想法。

這是我的新require.config:

require.config({ 
    urlArgs: "ts="+new Date().getTime(), // disable caching - remove in production 
    paths: { 
     jquery: [ 
      "http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min", 
      "libs/jquery" 
     ], 
     jqueryui: [ 
      "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min", 
      "libs/jqueryui" 
     ], 
     underscore: [ 
      "http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.3/underscore-min", 
      "libs/underscore" 
     ], 
     backbone: [ 
      "http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min", 
      "libs/backbone" 
     ] 
    }, 
    shim: { 
     'jqueryui': ['jquery'], 
     'underscore': ['jquery'], 
     'backbone': ['underscore'], 
     'core/core': ['underscore'], 
     'core/errors': ['core/core'], 
     'core/constants': ['core/core'] 
    } 
}); 
相關問題