什麼是RequireJS?
RequireJS是JavaScript檔的載入工具。 它能夠定義JavaScript檔案之間的相依性,讓瀏覽器以正確的順序載入JavaScript。 此外,它亦實作了AMD(Asynchronous Module Definition) API, 讓網頁開發者能將JavaScript程式碼進行良好的模組化設計。為何需要RequireJS?
大型Web應用程式開發者時常會面臨到JavaScript程式碼的維護問題:- 為了實作複雜的商業邏輯,JavaScript程式碼寫的又大又多。
- 使用了大量的第三方套件,套件之間還有相依性。
因此,Web應用程式的模組化設計,以及第三方套件的管理工具, 都是開發Web應用程式時需要審慎評估的。 而RequireJS正是一個不錯的選擇。
What is AMD?
AMD API定義了一個define方法, 旨在希望網頁開發者在撰寫一支JavaScript程式時, 能夠使用define方法來將其定義為一個「模組」, 一來避免大量的變數暴露在全域, 二來能使JavaScript的開發更為「模組化」。一般習慣下,一個JavaScript檔案會對應到一個模組,
define方法有三個參數:
define(id, dependencies, factory)
參數說明如下:id:模組名稱。一般習慣下,一個JavaScript檔案會對應到一個模組;此時通常會省略id。
dependencies:相依的模組名稱列表,為字串陣列型態。表示載入此模組載入前,需要先載入的模組。
factory:將此模組初始化或實例化的函式。此函式需要有回傳值,通常是代表此模組的物件,以讓其他模組使用該模組的方法。此外, 此函式的參數列, 將依序應到dependencies陣列中的模組。
以下以範例說明AMD API的使用, 假設有moduleA.js與moduleB.js兩個js檔,分別定義了兩個模組,內容如下:
moduleA.js
/* moduleA.js */
define([], //dependencies陣列
function() { //factory函式
var ModuleA = {
testExec : function() {
console.log("into ModuleA testExec");
}
};
return ModuleA;
}
);
moduleB.js/* moduleB.js */
define(["moduleA","module1","module2","module3"], //dependencies陣列
function(ModuleA,Module1,Module2,Module3) { //factory函式
var ModuleB = {
testExec : function() {
console.log("into ModuleB testExec");
ModuleA.testExec();
}
};
return ModuleB;
}
);
moduleA不相依於任何模組,dependencies陣列為空;moduleB相依於moduleA,module1,module2,module3, 注意其factory函式的參數,將依照順序對應到dependencies陣列中的模組。
此外,moduleB.js使用了moduleA.js中所定義的物件之方法, 其關係如下:
首先注意moduleB的factory函式中有一個參數,名為ModuleA, 其對應到dependencies參數中的模組名稱"moduleA"。 預設情況下,RequireJS將自動依當前相對路徑去尋找moduleA.js, 並將moduleA.js中的factory函式的回傳值載入。
同理,moduleB.js同樣地也可以使用module1.js,module2.js,module3.js中所定義的物件,此處就不再贅述。
如何使用在HTML檔中使用RequireJS載入JavaScript?
了解AMD API的使用方式後, 以下將說明如何使用RequireJS在HTML檔案中載入JavaScript程式。RequireJS本身也是一個JavaScript檔案,可以在RequireJS官方網站下載。
在HTML中使用RequireJS的方式如下:
<script data-main="js/main" src="path_to_requirejs"></script>
src是require.js檔的路徑。
data-main則指向RequireJS需要用到的設定檔,透過此設定檔,可以依據載入JavaScript模組並執行。該設定檔也是一個js檔案,且.js可以省略。
data-main設定檔最簡單的範例如下:main.js
require(['moduleB'], function(ModuleB){
ModuleB.testExec();
});
使用require.config的path參數設定模組別名
data-main設定檔中,還可以透過require.config的path參數設定模組的別名。這個參數尤其適用於是第三方JavaScript套件,如:main.js
require.config({
paths : {
'jquery' : 'lib/jquery-1.9.0'
}
});
require(['testloadlibs','jquery'], function(TestLoadLibs,JQuery){
TestLoadLibs.testExec();
});
testloadlibs.jsdefine(["jquery"],
function(jquery) {
var TestLoadLibs = {
testExec : function() {
console.log("into TestLoadLib testExec");
$(function(){
$(document.body).append("Hello jQuery!");
});
}
};
return TestLoadLibs;
}
);
如此一來,其他模組在需要使用jQuery的時候,不僅不需要打上詳細的lib/jquery-1.9.0相對路徑;更重要的是:當jQuery版本需要更動時,也只要修改main.js,而不需要修改其他模組。
結語
RequireJS不僅僅是JavaScript檔的載入工具,更是協助Web應用程式開發模組化以及管理第三方套件的利器。本文僅以最簡單的範例介紹RequireJS。事實上,光是require.config就提供了多種參數,以因應Web開發所可能遇到的各種情況,像是載入不支援以非AMD API開發的第三方JavaScript套件。 因此,RequireJS無疑是開發Web應用程式必學的套件之一。
Reference
初探RequireJS - 網站製作學習誌Javascript模块化编程(三):require.js的用法
沒有留言:
張貼留言