Requires強大靈活的運用是經過配置文件決定的。經過配置文件咱們能夠給模塊取別名、給模塊加上版本標識、設置模塊依賴、包裝非模塊等強大功能。同時RequireJS的優化器也大量使用了配置選項,若是你使用grunt、gulp等構建工具的話,也有必要深刻的學習配置文件的使用。javascript
下面經過示例來進行深度的探討配置文件的使用。css
配置文件的位置和聲明用法是相對於Requires這個腳本文件來決定的。假如配置文件在Requires腳本的下方,則能夠這樣使用:html
<script src="scripts/require.js"></script> <script> require.config({ baseUrl: "/another/path", paths: { "some": "some/v1.0" }, waitSeconds: 15 }); require( ["some/module", "my/module", "a.js", "b.js"], function(someModule, myModule) { //This function will be called when all the dependencies //listed above are loaded. Note that this function could //be called before the page is loaded. //This callback is optional. } ); </script>
這種狀況通常都是把配置參數寫到require.config裏面。若是配置文件在Requires腳本的上面,則是另一種用法了,示例代碼以下所示:java
<script> var require = { baseUrl: "/another/path", paths: { "some": "some/v1.0" }, waitSeconds: 15 }; </script> <script src="scripts/require.js"></script>
這種狀況下因爲require.js後加載,那麼直接使用require.config就會報錯,這時候就只能經過聲明一個全局的變量來注入配置參數來實現了。node
這時,你可能會發問了,改用那種狀況呢?我只能說根據你具體的業務來選擇某種場景。配置是活的,人也是活得。業務也是活的,因此這個沒有統一的答案,再有甚者,你能夠兩個結合使用。jquery
除了要注意配置文件的位置要靈活使用以外,如下有幾點仍是要注意的,這算是最佳實踐吧。git
在決定配置位置後,下面就是配置文件的參數了,RequireJS包含了大量的參數,這也是配置文件的核心,具體明細以下。github
全部模塊的查找根路徑。因此上面的示例中,"my/module"的標籤src值是"/another/path/my/module.js"。當加載純.js文件(依賴字串以/開頭,或者以.js結尾,或者含有協議),不會使用baseUrl。所以a.js及b.js都在包含上述代碼段的HTML頁面的同目錄下加載。npm
如未顯式設置baseUrl,則默認值是加載require.js的HTML所處的位置。若是用了data-main屬性,則該路徑就變成baseUrl。(因此最佳實踐仍是推重使用baseUrl)gulp
baseUrl可跟require.js頁面處於不一樣的域下,RequireJS腳本的加載是跨域的。惟一的限制是使用text! plugins加載文本內容時,這些路徑應跟頁面同域,至少在開發時應這樣。優化工具會將text! plugin資源內聯,所以在使用優化工具以後你可使用跨域引用text! plugin資源的那些資源。
path映射那些不直接放置於baseUrl下的模塊名(這至關於跟冗長的模塊名取個簡介的名字)。設置path時起始位置是相對於baseUrl的,除非該path設置以"/"開頭或含有URL協議(如http:)。在上述的配置下,"some/module"的script標籤src值是"/another/path/some/v1.0/module.js"。
用於模塊名的path不該含有.js後綴,由於一個path有可能映射到一個目錄。路徑解析機制會自動在映射模塊名到path時添加上.js後綴。在文本模版之類的場景中使用require.toUrl()時它也會添加合適的後綴。
在瀏覽器中運行時,可指定路徑的備選(fallbacks),以實現諸如首先指定了從CDN中加載,一旦CDN加載失敗則從本地位置中加載這類的機制。(回調函數,這個能夠跟蹤腳本加載是否成功。)
ps:paths映射的模塊不必定是標準的AMD模塊,可是最佳實踐推薦是有意義的模塊。
爲那些沒有使用define()來聲明依賴關係、設置模塊的"瀏覽器全局變量注入"型腳本作依賴和導出配置。
下面有個示例,它須要 RequireJS 2.1.0+,而且假定backbone.js、underscore.js 、jquery.js都裝於baseUrl目錄下。若是沒有,則你可能須要爲它們設置paths config:
requirejs.config({ //Remember: only use shim config for non-AMD scripts, //scripts that do not already call define(). The shim //config will not work correctly if used on AMD scripts, //in particular, the exports and init config will not //be triggered, and the deps config will be confusing //for those cases. shim: { 'backbone': { //These script dependencies should be loaded before loading //backbone.js deps: ['underscore', 'jquery'], //Once loaded, use the global 'Backbone' as the //module value. exports: 'Backbone' }, 'underscore': { exports: '_' }, 'foo': { deps: ['bar'], exports: 'Foo', init: function (bar) { //Using a function allows you to call noConflict for //libraries that support it, and do other cleanup. //However, plugins for those libraries may still want //a global. "this" for the function will be the global //object. The dependencies will be passed in as //function arguments. If this function returns a value, //then that value is used as the module export value //instead of the object found via the 'exports' string. //Note: jQuery registers as an AMD module via define(), //so this will not work for jQuery. See notes section //below for an approach for jQuery. return this.Foo.noConflict(); } } } }); //Then, later in a separate file, call it 'MyModel.js', a module is //defined, specifying 'backbone' as a dependency. RequireJS will use //the shim config to properly load 'backbone' and give a local //reference to this module. The global Backbone will still exist on //the page too. define(['backbone'], function (Backbone) { return Backbone.Model.extend({}); });
RequireJS 2.0.*中,shim配置中的"exports"屬性能夠是一個函數而不是字串。這種狀況下它就起到上述示例中的"init"屬性的功能。 RequireJS 2.1.0+中加入了"init"承接庫加載後的初始工做,以使exports做爲字串值被enforceDefine所使用。
那些僅做爲jQuery或Backbone的插件存在而不導出任何模塊變量的"模塊"們,shim配置可簡單設置爲依賴數組:
requirejs.config({ shim: { 'jquery.colorize': ['jquery'], 'jquery.scroll': ['jquery'], 'backbone.layoutmanager': ['backbone'] } });
但請注意,若你想在IE中使用404加載檢測以啓用path備選(fallbacks)或備錯(errbacks),則須要給定一個字串值的exports以使loader可以檢查出腳本是否實際加載了(init中的返回值不會用於enforceDefine檢查中):
requirejs.config({ shim: { 'jquery.colorize': { deps: ['jquery'], exports: 'jQuery.fn.colorize' }, 'jquery.scroll': { deps: ['jquery'], exports: 'jQuery.fn.scroll' }, 'backbone.layoutmanager': { deps: ['backbone'] exports: 'Backbone.LayoutManager' } } });
"shim"配置的重要注意事項:
shim配置僅設置了代碼的依賴關係,想要實際加載shim指定的或涉及的模塊,仍然須要一個常規的require/define調用。設置shim自己不會觸發代碼的加載。
請僅使用其餘"shim"模塊做爲shim腳本的依賴,或那些沒有依賴關係,而且在調用define()以前定義了全局變量(如jQuery或lodash)的AMD庫。不然,若是你使用了一個AMD模塊做爲一個shim配置模塊的依賴,在build以後,AMD模塊可能在shim託管代碼執行以前都不會被執行,這會致使錯誤。終極的解決方案是將全部shim託管代碼都升級爲含有可選的AMD define()調用。
"shim"配置的優化器重要注意事項:
您應當使用 mainConfigFile build配置項來指定含有shim配置的文件位置,不然優化器不會知曉shim配置。另外一個手段是將shim配置複製到build profile中。
不要在一個build中混用CDN加載和shim配置。示例場景,如:你從CDN加載jQuery的同時使用shim配置加載依賴於jQuery的原版Backbone。不要這麼作。您應該在build中將jQuery內聯而不是從CDN加載,不然build中內聯的Backbone會在CDN加載jQuery以前運行。這是由於shim配置僅延時加載到全部的依賴已加載,而不會作任何define的自動裝裹(auto-wrapping)。在build以後,全部依賴都已內聯,shim配置不能延時執行非define()的代碼。define()的模塊能夠在build以後與CDN加載代碼一併工做,由於它們已將本身的代碼合理地用define裝裹了,在全部的依賴都已加載以前不會執行。所以記住:shim配置僅是個處理非模塊(non-modular)代碼、遺留代碼的將就手段,如能夠應儘可能使用define()的模塊。
對於本地的多文件build,上述的CDN加載建議仍然適用。任何shim過的腳本,它們的依賴必須加載於該腳本執行以前。這意味着要麼直接在含有shim腳本的build層build它的依賴,要麼先使用require([], function (){})調用來加載它的依賴,而後對含有shim腳本的build層發出一個嵌套的require([])調用。
若是您使用了uglifyjs來壓縮代碼,不要將uglify的toplevel選項置爲true,或在命令行中不要使用 -mt。 該選項會破壞shim用於找到exports的全局名稱。
ps:shim配置是全部配置中最繁瑣也是最容易出問題的選項,我通常用來處理css依賴,最佳實踐是能不用,儘可能不用shim配置。
對於給定的模塊前綴,使用一個不一樣的模塊ID來加載該模塊。
該手段對於某些大型項目很重要:若有兩類模塊須要使用不一樣版本的"foo",但它們之間仍須要必定的協同。 在那些基於上下文的多版本實現中很難作到這一點。並且,paths配置僅用於爲模塊ID設置root paths,而不是爲了將一個模塊ID映射到另外一個。
map示例:
requirejs.config({ map: { 'some/newmodule': { 'foo': 'foo1.2' }, 'some/oldmodule': { 'foo': 'foo1.0' } } });
若是各模塊在磁盤上分佈以下:
當「some/newmodule」調用了「require('foo')」,它將獲取到foo1.2.js文件;而當「some/oldmodule」調用「`require('foo')」時它將獲取到foo1.0.js。
該特性僅適用於那些調用了define()並將其註冊爲匿名模塊的真正AMD模塊腳本。而且,請在map配置中僅使用絕對模塊ID,「../some/thing」之類的相對ID不能工做。
另外在map中支持「*」,意思是「對於全部的模塊加載,使用本map配置」。若是還有更細化的map配置,會優先於「*」配置。示例:
requirejs.config({ map: { '*': { 'foo': 'foo1.2' }, 'some/oldmodule': { 'foo': 'foo1.0' } } });
意思是除了「some/oldmodule」外的全部模塊,當要用「foo」時,使用「foo1.2」來替代。對於「some/oldmodule」本身,則使用「foo1.0」。
PS:map提供了統一腳本,不一樣版本的支持。
經常須要將配置信息傳給一個模塊。這些配置每每是application級別的信息,須要一個手段將它們向下傳遞給模塊。在RequireJS中,基於requirejs.config()的config配置項來實現。要獲取這些信息的模塊能夠加載特殊的依賴「module」,並調用module.config()。示例:
requirejs.config({ config: { 'bar': { size: 'large' }, 'baz': { color: 'blue' } } }); //bar.js, which uses simplified CJS wrapping: //http://requirejs.org/docs/whyamd.html#sugar define(function (require, exports, module) { //Will be the value 'large' var size = module.config().size; }); //baz.js which uses a dependency array, //it asks for the special module ID, 'module': //https://github.com/jrburke/requirejs/wiki/Differences-between-the-simplified-CommonJS-wrapper-and-standard-AMD-define#wiki-magic define(['module'], function (module) { //Will be the value 'blue' var color = module.config().color; });
若要將config傳給包,將目標設置爲包的主模塊而不是包ID:
requirejs.config({ //Pass an API key for use in the pixie package's //main module. config: { 'pixie/index': { apiKey: 'XJKDLNS' } }, //Set up config for the "pixie" package, whose main //module is the index.js file in the pixie folder. packages: [ { name: 'pixie', main: 'index' } ] });
PS: config在個人項目中沒有被用到過,不過值得關注,另外對於第二種狀況,本人不太熟悉,後期會開一篇文章介紹。
從CommonJS包(package)中加載模塊。參見從包中加載模塊。(連接:http://requirejs.cn/docs/commonjs.html)
PS:目前還沒遇到這樣的場景,關注中...
Node treats module ID example.js and example the same. By default these are two different IDs in RequireJS. If you end up using modules installed from npm, then you may need to set this config value to true to avoid resolution issues。
(翻譯:Node對待模塊example.js和example是同樣的.默認在RequireJS中有兩個不一樣的標識。若是你經過npm安裝且使用模塊結束,那麼你可能須要設置這個參數爲true來避免這個問題。)
在放棄加載一個腳本以前等待的秒數。設爲0禁用等待超時。默認爲7秒。
命名一個加載上下文。這容許require.js在同一頁面上加載模塊的多個版本,若是每一個頂層require調用都指定了一個惟一的上下文字符串。想要正確地使用,請參考多版本支持一節。
指定要加載的一個依賴數組。當將require設置爲一個config object在加載require.js以前使用時頗有用。一旦require.js被定義,這些依賴就已加載。使用deps就像調用require([]),但它在loader處理配置完畢以後就當即生效。它並不阻塞其餘的require()調用,它僅是指定某些模塊做爲config塊的一部分而異步加載的手段而已。
在deps加載完畢後執行的函數。當將require設置爲一個config object在加載require.js以前使用時頗有用,其做爲配置的deps數組加載完畢後爲require指定的函數。
若是設置爲true,則當一個腳本不是經過define()定義且不具有可供檢查的shim導出字串值時,就會拋出錯誤。參考在IE中捕獲加載錯誤一節。
若是設置爲true,則使用document.createElementNS()去建立script元素。
RequireJS獲取資源時附加在URL後面的額外的query參數。做爲瀏覽器或服務器未正確配置時的「cache bust」手段頗有用。使用cache bust配置的一個示例:
urlArgs: "bust=" + (new Date()).getTime()
在開發中這頗有用,但請記得在部署到生成環境以前移除它。
指定RequireJS將script標籤插入document時所用的type=""值。默認爲「text/javascript」。想要啓用Firefox的JavaScript 1.8特性,可以使用值「text/javascript;version=1.8」。
Introduced in RequireJS 2.1.9: If set to true, skips the data-main attribute scanning done to start module loading. Useful if RequireJS is embedded in a utility library that may interact with other RequireJS library on the page, and the embedded version should not do data-main loading.
(翻譯:在2.1.9中被引入:若是設置爲true,就會跳過data-main屬性的掃描啓動模塊的加載。若是RequireJS嵌入到一個通用的庫中以其餘頁面中的RequireJS交互,且嵌入的版本不會使用data-main加載)
PS:翻譯不標準,請告知,另外這個屬性用的很少,暫時沒什麼實踐經驗。
官網:http://requirejs.org/docs/api.html#config
中文翻譯:http://requirejs.cn/docs/api.html#config
ps:翻譯不標準、涉及文章侵權、文章有錯誤的地方請告知。