[Javascript] Require.js — JS代碼的模組化

Dosmanthus
5 min readMay 3, 2017

--

隨著前端程式量的增多,以往使用html tag同步載入javascript的方式會造成阻塞的情況發生,關聯檔案及加載順序也變得難以管理。假設有10個 JS 檔案需要下載,而瀏覽器一般會啟用 2~6個執行緒來平行下載,那麼其他的資源要等到前6個執行緒中的任何一個完成之後才能開始,這樣會造成頁面空白等待。為了解決這個問題, CommonJS 社群提出了 AMD(Asynchronous Module Definition) 規範,而 Require.js 則是 AMD 最好的實現之一。

AMD

AMD 規範提出一種基於模組的異步(asynchronous)載入 JS 代碼的機制,依照模組的依賴關係來延遲載入需要的代碼。依賴模組的代碼,都定義在一個回呼函數中,等到載入完畢後才會運行。這種方式使頁面上其他不依賴 JS 代碼的元素可以先載入,提升頁面的載入速度,使用戶得到更好的使用體驗。

Require.js

Require.js 主要提供2個功能:

  • 異步載入 JS,避免網頁失去響應。
  • 管理模組之間的依賴性,有助於代碼的維護。

在以往的方式中,假設main.js執行前需要先載入1~4的JS檔案:

<script src="1.js"></script>
<script src="2.js"></script>
<script src="3.js"></script>
<script src="4.js"></script>
<script src="main.js"></script>

使用 require.js 載入時,只需將代碼改寫為:

<script src="libs/requirejs/require.js" data-main="main" ></script>

然後,將main.js修改為:

require(["a","b","c","d"],function(a,b,c,d){
//原本的程式碼
});

Require.js 會先尋找 data-main 屬性指定的檔案名稱(省略副檔名),依序載入 require 函數中第一個參數的模組陣列,等到關聯的模組都載入完畢之後才會執行回呼函數。

定義一個模組

使用 define 函數來定義模組:

# math.js
define(function(){
var add = function (x,y) {
return x+y ;
};
return {
add: add
};
});
# main.js
require(['math'], function(){
alert(math.add(1,1))
});

如果這個模組還依賴其他的模組,那麼define 函數的第一個參數必須是一個關聯模組的陣列。

define([moduleA], function(){
function foo(){
moduleA.doSomething();
}
return {
foo: foo
}
});

Config 方法

如果需要載入非採用AMD規範的模組時,需要先用 require.config()方法來定義。

require.config({
paths: {
'underscore': 'libs/underscore/underscore'
},
shim: {
'underscore': {
exports: '_'
}
}
});

paths 屬性定義了underscore 模組對應的檔案位置。shim 屬性定義的 exports 值,表示的是這個模組被外部調用時的名稱。除了 exports 值外,還可以定義 deps,表明該模組的依賴性。

require.config({
shim: {
'underscore': {
exports: '_'
},
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
}
}
});

ES6模組系統

ES6中加入了模組系統的支援,使用export與import來進行模組輸出與輸入。

# lib.js
export default greeting() {
return "Hello, World!" ;
}
# import
import greeting from './lib.js'

更多介紹: ES6 模組系統

參考:

--

--