轉自:http://home.cnblogs.com/u/snandy/css
1、node
加載JavaScript文件:
RequireJS的目標是鼓勵代碼的模塊,它使用不一樣於傳統<script>標籤的腳本加載步驟。
能夠用它來加速、優化代碼,但其主要目的仍是爲了代碼的模塊化,它鼓勵在使用腳本時以
module ID替代URL地址
RequireJS以一個相對於baseUrl的地址來加載全部的代碼,頁面頂層<script>標籤含有一個特殊
的屬性data-main,require.js使用他來啓動腳本加載過程,而baseUrl通常設置到與該屬性相一致
的目錄,下列示例中展現baseUrl的設置:
<script data-main="scripts/main.js" src="scripts/require.js"></script>
baseUrl亦可經過RequireJS config手動設置,若是沒有顯示指定config及data-main,則默認的baseUrl
爲包含RequireJS的那個HTML頁面的所屬目錄。
RequireJS默認全部的依賴資源都是js腳本,所以無需在module ID上再添加「.js」後綴
RequireJS在進行moduleID到path的解析時會自動補上後綴,你能夠經過paths config設置一組腳本,
這是有助於咱們在使用腳本時碼更少的字
有時候你想避開「baseUrl+paths」的解析過程,而是直接指定加載某一個目錄下的腳本,此時能夠這樣作:
若是一個module ID符合下述規則之一,其ID解析會避開常規的「baseUrl+paths」配置,而是直接將其加載爲
一個相對於當前HTML文檔的腳本:
·以「.js」結束
·以「/」開始
·包含URL協議,如「http:」or「https:」
通常來講,最好仍是使用baseUrl及「paths」 config去設置module ID。它會給你帶來額外的靈活性,
如便於腳本的重命名、重定位等。同時,爲了不凌亂的配置,最好不要使用多級嵌套的目錄層次來
組織代碼,而是要麼將全部的腳本都放置到baseUrl中,要麼分置爲項目庫/第三方庫的一個扁平結構,以下:jquery
注意在示例中,三方庫jQuery沒有將版本號包含在他們的文件夾中。咱們建議將版本信息放置在單獨的文件中來
進行跟蹤。使用諸如volo這類的工具,能夠將package.json打上版本信息,並在磁盤上保持文件名爲‘jquery.js’
這有助於你保持配置的最小化,避免爲每一個庫版本設置一條path,例如,將‘jquery’配置爲「jquery-1.7.2」ajax
理想情況下,每一個加載的腳本都是經過define()來定義的一個模塊;但有些「瀏覽器全局變量注入」型的傳統/遺留庫
並無使用define()來定義它們的依賴關係,你必須爲此使用shim config來指明它們的依賴關係,若是你沒有
指明依賴關係,加載可能報錯,這是由於基於速度的緣由,RequireJS會異步地以無序的形式加載這些庫json
data-main入口點:
require.js在加載的時候會檢查data-main屬性:
<script data-main="scripts/main" src="scripts/require.js"></script>
你能夠在啊data-main指向的腳本中設置模塊加載選項,而後加載第一個應用模塊。注意:你在main.js中所設置
的腳本是異步加載的,因此若是你在頁面中配置了其餘JS加載,則不能保證它們所依賴的JS已經加載成功api
例如:
<script data-main="scripts/main" src="scripts/require.js"></script>
<script src="scripts/other.js"></script>數組
//contents of main.js:
require.config({
paths : {
foo : 'libs/foo-1.1.3'
}
})瀏覽器
//contents of other.js:
//This code might be called before the require.config() in main.js
//has executed When that happens, require.js will attempt to
//load 'scripts/foo.js' instead of 'scripts/libs/foo-1.1.3.js'
require(['foo'],function(foo){
});安全
定義模塊:
模塊不一樣於傳統的腳本文件,他良好的定義了一個做用域來避免全局名稱空間污染,它能夠顯式
地列出其依賴關係,並以函數(定義此模塊的那個函數)參數的形式將這些依賴進行注入,而無需
引用全局變量,Require.js的模塊是模塊模式的一個擴展,其好處是無需全局地引用其餘模塊
require.js的模塊語法容許它儘快地加載多個模塊,雖然加載的順序不訂,但依賴的順序最終
是正確的,同時由於無需建立全局變量,甚至能夠作到在同一個頁面上同時加載同一模塊的不一樣版本
一個磁盤文件應該只定義1個模塊,多個模塊可使用內置優化工具將其組織打包。
一、簡單的值對:
若是一個模塊僅含值對,沒有任何依賴,則在define()中定義這些值對就行了:
define({
color:'black',
size:'unisize'
})
二、函數式定義:
若是一個模塊沒有任何依賴,但須要一個作setup工做的函數,則在define()中定義該函數
,並將其傳給define()
define(function(){
return {
color:'black',
size:'unisize'
}
});
三、存在依賴的函數式定義:
若是模塊存在依賴:則第一個參數是依賴的名稱數組;第二個參數是函數,在模塊的全部依賴加載
完畢後,該函數會被調用來定義該模塊,所以該模塊應該返回一個定義本模塊的object,依賴關係
會以參數的形式注入到該函數上,參數列表與依賴名稱列表一一對應。
define(['./cart','./inventory'],function(cart,inventory){
return {
color:'blue',
size:'large',
addTocart:function(){
inventory.decrement(this);
cart.add(this);
}
}
})
本示例建立了一個my/shirt模塊,它依賴於my/cart及my/inventory。磁盤上各文件分佈以下:
· my/cart.js
· my/inventory.js
· my/shirt.js
模塊函數以參數‘cart’及‘inventory’使用這兩個以‘./cart’及‘./inventoty’名稱指定的模塊
在這兩個模塊加載完畢以前,模塊函數不會被調用
嚴重不鼓勵模塊定義全局變量,遵循此處的定義模式,可使得同一模塊的不一樣版本並存於同一
頁面上,另外,函參的順序應與依賴順序保存一致
返回的object定義了'my/shirt'模塊,這種定義模式下,‘my/shirt’不做爲一個全局變量而存在
四、將模塊定義爲一個函數:
對模塊的返回值類型並無強制爲必定是個object,任何函數的返回值都是容許的,此處是一個返
回了函數的模塊定義:
define(['my/cart','my/inventory'],function(cart,inventory){
return function(title){
return title?(window.title=title):inventory.storeName +'' +cart.name;
}
})
五、簡單包裝CommonJS來定義模塊
若是你現有一些以CommonJS模塊格式編寫的代碼,而這些代碼難於使用上述依賴名稱數組參數的形式
來重構,你能夠考慮直接將這些依賴對應到一些本地變量中進行使用,你可使用一個CommonJS的簡
單包裝來實現:
define(function(require,exports,module){
var a = require('a'),
b = require('b');
return function(){};
})
該包裝方法依靠Function.prototype.toString()將函數內容賦予一個有意義的字串值,但在一些設備
如PS3及一些老的Opera手機瀏覽器中不起做用,考慮在這些設備上使用優化器將依賴導出爲數組形式
六、定義一個命名模塊:
你能夠會看到一些define()中包含了一個模塊名稱做爲首個參數:
define('foo/title',['my/cart','my/inventory'],function(cart,inventory){
})
這些常由優化工具生成,你也能夠本身顯示指定模塊名稱,但這使模塊更不具有移植性--就是說若你
將文件移動到其餘目錄下,你就得重命名,通常最好避免對模塊硬編碼,而是交給優化工具去生成,
優化工具須要生成模塊名以將多個模塊打成一個包,加快到瀏覽的載入速度
其餘注意事項:
一個文件一個模塊:每一個JavaScript文件應該只定義一個模塊,這是模塊名-至-文件名查找機制的
天然要求。多個模塊會被優化工具組織優化,但你在使用優化工具時,應將多個模塊放置到一個文件中
define()中的相對模塊名:爲了能夠在define()內部使用諸如require('./relative/name')的調用以
正確解析相對名稱,記得將‘require’自己做爲一個依賴諸如到模塊中:
define(['require'.'./relative/name'],function(require){
var mod = require('./ralative/name');
})
或者更好地,使用下述爲轉換CommonJS模塊所設的更短的語法:
define(function(require){
var mod = require('./relative/name');
})
相對路徑在一些場景下格外有用,例如:爲了以便於將代碼共享給其餘人或項目,你在某個目錄下建立
了一些模塊,你能夠訪問模塊的相鄰模塊,無需知道該目錄的名稱,
生成相對於模塊的URL地址:你可能須要生成一個相對於模塊的URL地址,你能夠將'require'做爲一個依賴
注入進來,而後調用require.toUrl()以生成該URL:
define(['require'],function(require){
var cssUrl = require.toUrl('./style.css');
})
控制檯調試:若是你須要處理一個已經過require(['module/name'],function(){})
調用加載了的模塊,可使用模塊名做爲字符串參數的require()調用來獲取它:
require('module/name').callSomeFunction()
注意這種形式僅在「module/name」已經由其異步形式的require(['module/name'])加載
了後纔有效,只能在define內部使用形如「./module/name」的相對路徑app
循環依賴:
若是你定義了一個循環依賴(a依賴b,b同時依賴a),則在這種情形下當b的模塊函數被
調用的時候,它會獲得一個undefined的a,b能夠在模塊已經定義好後用require()方法再獲取
(記得將require做爲依賴注入進來):
define(['require','a'],function(require,a){
return function(title){
return require('a').doSomething();
}
})
通常說來你無需使用require()去獲取一個模塊,而是應當使用注入到模塊函數中的依賴。
循環依賴比較罕見,這也是一個重構代碼從新設計的警示燈,但無論怎樣,有時候仍是要
用到循環依賴,這種情形下就使用上述的require()方式來解決。
若是你熟悉CommonJS,你能夠考慮使用exports爲模塊創建一個空object,該object能夠當即
被其餘模塊引用,在循環依賴的兩頭都如此操做以後,你就能夠安全地持有其餘模塊了,這種
方法僅在每一個模塊都是輸出object做爲模塊值的時候有效,換成函數無效
define(function(require,exports,module){
var a = require('a');
exports.foo = function(){
return a.bar();
}
})
或者,若是你使用依賴注入數組的步驟,則可用注入特殊的"exports"來解決
2、requireJS的升級發生的變化:
一、延遲模塊的執行:之前模塊加載後factory立馬執行,性能上確定會有一些損耗,如今能夠等到
require的時候才執行
二、config增長了shim、map、module、enforceDefine
shim參數解決了使用非AMD方式定義的模塊(如jQuery插件)及其載入順序,使用shim參數來取代
1.0版本的order插件其實在1.0版本中就曾經有人開發過use和wrap插件來解決此類問題,考慮到很
多開發者有此類需求(好比某些JS模塊是較早時候其餘人開發的,非AMD方式)這次2.0版本直接將其
內置其中
下面是一個使用jQuery插件形式配置的參數,咱們知道jQuery插件本質上是將命名空間掛在全局的jQuery
或jQuery.fn上,而非使用define定義的 模塊,而jQuery插件都依賴於jQuery,即在require插件時得保證
jQuery先下載下來,能夠以下配置:
require.config({
shim:{
'jquery-slide':['jquery']
}
});
require(['jquery-slide'],function(){
})
這時會保證下下載jquery.js,而後在下載jquery-slide.js
map參數用來解決同一模塊的不一樣版本問題,這一靈感來自於Dojo的packageMap。有這樣的場景:
開發初期使用了的jquery-1.6.4,後期升級到了1.7.2,但擔憂有些依賴jquery-1.6.4的代碼升級到
1.7.2後有問題,所以保守的讓這部分代碼繼續使用1.6.4版本,這時map參數將派上用場。假如A,B
模塊中使用了jquery-1.6.4.js,C,D模塊中使用了jquery-1.7.2.js。以下:
require.config({
map:{
'A':{
'jquery':'jquery-1.6.4'
},
'B':{
'jquery':'jquery-1.7.4'
}
}
})
require(['A'])將會下載jquery-1.6.4,require(['B'])會下載jquery-1.7.2。若是模塊A寫成*
則表示除了B模塊使用jquery-1.7.2以外其餘模塊都是用jquery-1.6.4,map參數解決了模塊的各
個版本問題,很好的向下兼容了老代碼
config參數用來給指定的模塊傳遞一些有用的數據,以下;
require.config({
config: {
'A':{
info : {name :'jack'}
}
}
})
使用A的模塊中能夠經過A.config().info獲取到該數據信息。如
require(['A'],function(A){
var info = A.config().info;
console.log(info);
})
enforceDefine用來強制模塊使用define定義,默認爲false,如underscore再也不支持AMD後
其代碼移除了define,此時若是仍然使用requirejs來載入他, 他就是普通的js文件了,此時
若是enforceDefine設爲true,雖然underscore.js能下載,但requirejs會報錯,
require函數增長了第三個參數errbacks
很明顯該函數指模塊文件沒有載入成功時的回調
require(['b'],function(){
console.log('success')
},function(err){
console.log(err)
})
err會給出一些出錯提示信息
更強大的paths參數:
能夠配置成一個數組,順序映射,當前面的路徑沒有成功載入,能夠接着使用後面的路徑
require.config({
enforceDefine:true,
paths:{
jquery:[
'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min',
'lib/jquery'
]
}
})
require(['jquery'],function($){
})
在模塊載入失敗回調中可使用undef函數移除模塊的註冊:
require(['jquery'],function($){
},function(err){
var failedId = err.requireModules && err.requireModules[0];
if(failId === 'jquery'){
requirejs.undef(failedId)
}
})
2、壓縮
壓縮:
node r.js -o baseUrl=js name=main out=built.js
-o表示優化,該參數是固定的,必選
baseUrl值存放模塊的跟目錄,這裏是r4/js,由於cd到r4中了,只需設置爲js,可選,若是沒有設置將從
r4中查找main.js,
main 模塊的入口文件,這裏設置成main,那麼r.js會從baseUrl+main去查找,這裏實際是r4/js/main.js
找出其所依賴的全部其餘模塊,而後合併壓縮
out 指合併壓縮後輸出的文件路徑,這裏直接是built.js,那麼輸出到根目錄r4下
2個參數:
excludeShallow 合併時將排除該文件
node r.js -o baseUrl=js name=main out=built.js excludeShallow=selector
optimize(none/uglify/closure)指定是否壓縮,默認爲uglify
不傳該參數時r.js默認以uglifyJS壓縮,設置爲none則不會壓縮,僅合併,這在開發階段是頗有用的
node r.js -o baseUrl=js name=main out=built.js optimize=none 這時生成的built.js是沒有壓縮的