2012-06-06 46 views
58

我們正在構建一個使用Backbone,RequireJS和Handlebars的非trival web應用程序,以及我只是好奇而已。目前,我們的每個模型的八九不離十是這樣的:如何使用RequireJS實現延遲加載?

define(['Backbone', 'js/thing/a', 'js/thing/b', 'js/lib/bob'], function(a, b, bob) { 
    return Backbone.Router.extend({ 
    // stuff here 
    }); 
}); 

那裏的東西/一,東西/ B都有自己的依賴關係,例如在車把模板等什麼,現在的情況是,在我的主.js,所有'頂級'路由器都被加載並初始化;每個頂級路由器都有一組依賴項(模型,視圖等),每個依賴項都有自己的依賴關係(模板,幫助程序,utils等)。基本上,一個大樹結構。

這種情況下的問題是整個樹在頁面加載時被解析和加載。我不介意這樣做,因爲我們最終將通過優化器運行它,並最終得到一個大的單個文件(將RequireJS降低爲基本模塊化框架)。不過,我很好奇你是否可以按需求加載視圖和模板等內容。

有「簡化CommonJS的包裹解釋說:」 here,所以我試過了:

define(function(require) { 
    Backbone = require('Backbone'); 
    return Backbone.Router.extend({ 
    doStuff: function() { 
     var MyView = require('js/myView'); 
     new MyView().render(); 
    } 
    }); 
}); 

不過,看着Chrome的網絡督察,似乎RequireJS - 不知何故,即使沒有觸發觸發路線doStuff處理程序 - 仍然加載myView依賴項。問題:

  • 這實際上是可能的嗎? RequireJS中是否有黑色磁磚,可以在不觸發doStuff路線的情況下尋找require()的電話?
  • 這是理論上正確的方式來進行'按需'延遲加載RequireJS模塊和資源嗎?
  • 如果你使用這個表示法,r.js優化器是否仍然像廣告一樣工作?

回答

48

這實際上可能嗎? RequireJS中是否存在黑色磁磚,用於查找調用require()而不實際觸發doStuff路徑?

當你使用「糖」語法it uses Function.prototype.toString and a regex解壓到您的require引用,然後列出它們作爲依賴運行函數之前。基本上它成爲第一個參數deps數組定義的正常樣式。因此,它並不關心你的需求調用的位置,這就是爲什麼條件語句被忽略的原因(它也解釋了爲什麼這些require調用必須使用字符串字面值而不是變量)。

這是要去關於「點播」理論上正確的方式,RequireJS模塊和資源延遲加載?

使用糖語法將不允許有條件加載,如你所見。我能想到的把我的頭頂部的唯一方法是使用require電話與DEPS數組和一個回調:

define(function(require) { 
    var module1 = require('module1'); 

    // This will only load if the condition is true 
    if (true) { 
     require(['module2'], function(module2) { 

     }); 
    } 

    return {}; 
}); 

唯一的缺點是另一個嵌套的功能,但如果你的表現後,那麼這是一條有效的路線。

如果你使用這個表示法,r.js優化器是否仍然像廣告一樣工作?

如果你使用'糖'語法,那麼是的,優化器將正常工作。舉個例子:

模塊/ test.js

define(function(require) { 
    var $ = require('jquery'); 
    var _ = require('underscore'); 

    return { 
     bla: true 
    } 
}); 

一旦被r.js這看起來像編譯:

define('modules/test', ['require', 'jquery', 'underscore'], function(require) { 
    var $ = require('jquery'); 
    var _ = require('underscore'); 

    return { 
     bla: true 
    } 
}); 

總之,你可以有條件地加載的東西,但你所說的,如果你打算用r.js來優化項目,那麼在使用糖語法時沒有太大的開銷。

3

您可能還想看看require-lazy。它具有運行時組件和構建時間組件。運行時組件,您可以懶洋洋地需要一個模塊(注意lazy!插件):

define(["lazy!mymodule"], function(mymodule) { 
    ... 
}); 

在前面的背景下,mymodulepromise,真正的模塊將被裝載get()並在將提供then()回調:

mymodule.get().then(function(m) { 
    // here m is the real mymodule 
}); 

要求,慵懶r.js集成,自動生成的JavaScript文件「捆綁」。它還自動處理捆綁包的緩存清除。有幾個例子可以得到一個想法。還有GruntBower的整合。