1. 程式人生 > >前端模組化——RequireJS

前端模組化——RequireJS

        為什麼模組很重要?

        因為有了模組,我們就可以更方便地使用別人的程式碼,想要什麼功能,就載入什麼模組。

        但是,這樣做有一個前提,那就是大家必須以同樣的方式編寫模組。目前,通行的Javascript模組規範共有兩種:CommonJS和AMD。

        AMD是"Asynchronous Module Definition"的縮寫,即"非同步模組定義"。它採用非同步方式載入模組,模組的載入不影響它後面語句的執行。所有依賴這個模組的語句,都定義在一個回撥函式中,等到載入完成之後,這個回撥函式才會執行。

        目前,主要有兩個Javascript庫實現了AMD規範:require.js和curl.js。

        RequireJS是一個非常小巧的JavaScript模組載入框架,是AMD規範最好的實現者之一。它可以和其他的框架協同工作,使用RequireJS必將使您的前端程式碼質量得以提升。

以前載入js檔案是這樣的:

    <script src="a.js"></script>
    <script src="b.js"></script>
    <script src="c.js"></script>
    <script src="d.js"></script>
    <script src="e.js"></script>
    <script src="f.js"></script>
    <script src="g.js"></script>
    <script src="h.js"></script>
    <script src="i.js"></script>
    <script src="j.js"></script>

這樣寫有很多缺點:

1、載入時,瀏覽器會停止網頁渲染,載入檔案越多,網頁失去響應時間就會越長;

例如:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="index.js"></script>
</head>
<body>
<div>body</div>
</body>
</html>

index.js

(function(){
    alert("hello");
}());

        開啟瀏覽器,發現頁面先彈出彈框,然後一直在載入,不點選確定,頁面載入不出來,只有點選確定以後,頁面內容才會加載出來。


2、由於js檔案之間存在依賴關係,因此必須嚴格保證載入順序(比如上例的a.js要在b.js的前面),依賴性最大的模組一定要放到最後載入,當依賴關係很複雜時,程式碼編寫和維護就會變得困難。

        require.js的誕生,就是為了解決這兩個問題:

1、實現js檔案的非同步載入,這樣就可以防止js載入阻塞頁面渲染,導致網頁失去響應;

2、管理模組之間的依賴性,便於程式碼的編寫和維護。

RequireJS的用法:

一、引入require.js檔案

        為了避免載入這個檔案,也可能造成網頁失去響應。可以把它放在網頁底部載入,或是:

<script src="require.js" defer async="true"></script>

        async屬性表明這個檔案需要非同步載入,避免網頁失去響應。IE不支援這個屬性,只支援defer,所以把defer也寫上。

二、載入自己js檔案

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

        data-main屬性的作用是,指定網頁程式的主模組。

        上面網頁程式的主模組就是main.js,意思就是,整個網頁的入口程式碼。這個檔案會第一個被require.js載入。由於require.js預設檔案字尾名是js,所以可以把main.js簡寫成main。

三、書寫主模組 main.js:require()函式

        主模組依賴於其他模組,這時就要使用AMD規範定義的的require()函式

語法:

require(['module1','module2','module3', ...],function(module1,module2,module3, ...){
    //主模組的程式碼就寫在回撥函式中
});

        第一個引數:一個數組,表示所依賴的模組,即其他的js檔案。第二個引數:一個回撥函式。

        require()非同步載入其他模組,只有當前面指定的模組都載入成功後,回撥函式才會被呼叫。載入的模組會以引數形式傳入該回調函式,從而在回撥函式內部就可以使用這些模組。

四、模組的載入:require.config()方法

        如果主模組所依賴的其他模組跟main.js在同一目錄下,第三步的寫法,模組就會自動載入。但是,很多情況下,並不是所有模組都在一個目錄下,這就需要使用require.config()方法,可以對模組的載入行為進行自定義。

        require.config()就寫在主模組(main.js)頭部。引數是一個物件,這個物件的paths屬性指定各個模組的載入路徑。

例如:main.js依賴js目錄下的三個檔案,有兩種寫法

1、逐一指定路徑。

require.config({
    paths:{
        "food":"js/food",
        "snake":"js/snake",
        "game":"js/game"
    }
});

2、直接改變基目錄(baseUrl)。

require.config({
    baseUrl:"js",
    paths:{
        "food":"food",
        "snake":"snake",
        "game":"game"
    }
});

載入方法:

require(['food','snake','game'],function(food,snake,game){
//主模組程式碼
});

如果某個模組在另一臺主機上,也可以直接指定它的網址,比如:

require.config({
    paths: {
        "jquery": "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min"
    }
});

        require.js要求,每個模組是一個單獨的js檔案。這樣,如果載入多個模組,就會發出多次HTTP請求,會影響網頁的載入速度。因此,require.js提供了一個優化工具 r.js。

        當模組部署完畢以後,可以用 r.js優化頁面中的js指令碼和css檔案,以提高頁面響應速度,減少頁面http/https請求次數。

        r.js的優化分為兩種方式:一是壓縮js和css檔案,也就是去掉空格,空行,將長變數名換成短變數名之類的;二是合併多個js檔案為一個js檔案,合併多個css檔案為一個。

五、AMD模組的寫法:define()函式

        require.js載入的模組,採用AMD規範。即:模組必須按照AMD的規定來寫。就是模組必須採用特定的define()函式來定義。

        如果一個模組不依賴其他模組,可直接定義在define()函式中。

        假定有一個math.js檔案,定義了一個math模組。那麼,math.js就要這樣寫:

// math.js
define(function (){
    var add = function (x,y){
        return x+y;
    };
    return {
        add: add
    };
});

        如果一個模組還依賴其他模組,那麼define()函式的第一個引數,必須是一個數組,指明該模組的依賴性。

define(['math'], function(math){
    var result = function (x,y){
        return math.add(x,y)*math.add(x,y);
    };
    return {
        result: result
    };
});

當require()函式載入上面這個模組的時候,就會先載入math.js檔案。

六、載入非規範的模組:shim屬性

       有一部分流行的函式庫(比如jQuery)符合AMD規範,但是也有更多的庫並不符合。那麼,require.js是怎樣載入非規範的模組呢?

        非規範模組在用require()載入之前,要先用require.config()方法,定義它們的一些特徵。

        require.config()接受一個配置物件,這個物件除了有paths屬性外,還有一個shim屬性,專門用來配置不相容的模組。

        非規範模組要定義(1)exports值(輸出的變數名),表明這個模組外部呼叫時的名稱;(2)deps陣列,表明該模組的依賴性。

比如,jQuery的外掛可以這樣定義:
require.config(
    shim: {
        'jquery.scroll': {
            deps: ['jquery'],
exports: 'jQuery.fn.scroll'
}
    }
);
七、require.js外掛
require.js還提供一系列外掛,實現一些特定的功能。
domready外掛,可以讓回撥函式在頁面DOM結構載入完成後再執行。
text和image外掛,允許require.js載入文字和圖片檔案。
json和mdown外掛,用於載入json檔案和markdown檔案

參考資料: