RequireJS學習總結

RequireJS是一個工具庫,主要用於客戶端的模塊管理。它可以讓客戶端的代碼分成一個個模塊,實現異步或動態加載,從而提高代碼的性能和可維護性。它的模塊管理遵守AMD規範。
RequireJS的基本思想是:通過define方法,將代碼定義爲模塊;通過require方法,實現代碼的模塊加載。
首先下載require.js文件傳送門
然後,將require.js嵌入網頁,然後就能在網頁中進行模塊化編程了

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

上面的scripts/main是我們腳本的入口文件main.js

define方法:定義模塊

define方法用於定義模塊,RequireJS要求每個模塊放在一個單獨的文件裏。
按照是否依賴其他模塊,可以分成兩種情況:

  • 定義獨立模塊,即所定義的模塊不依賴其他模塊
    示例:
define({
    method1: function() {},
    method2: function() {},
});

上面代碼生成了一個擁有method1、method2兩個方法的模塊
或者這樣寫:把對象寫成一個函數,該函數的返回值就是輸出的模塊。

define(function () {
    return {
        method1: function() {},
        method2: function() {},
    };
});

一般採用後一種寫法,這樣可以在函數體內寫一些模塊初始化代碼。
此外,define定義的模塊可以返回任何值,不限於對象。
- 定義非獨立模塊,即所定義的模塊依賴於其他模塊

define(['module1', 'module2'], function(m1, m2) {
   return {
        method: function() {
            m1.methodA();
            m2.methodB();
        }
    };
});

define方法的第一個參數是一個數組,它的成員是當前模塊所依賴的模塊。比如,[‘module1’, ‘module2’]表示我們定義的這個新模塊依賴於module1模塊和module2模塊,只有先加載這兩個模塊,新模塊才能正常運行。一般情況下,module1模塊和module2模塊指的是,當前目錄下的module1.js文件和module2.js文件,等同於寫成[‘./module1’, ‘./module2’]。
define方法的第二個參數是一個函數,當前面數組的所有成員加載成功後,它將被調用。它的參數與數組的成員一一對應,比如function(m1, m2)就表示,這個函數的第一個參數m1對應module1模塊,第二個參數m2對應module2模塊。這個函數必須返回一個對象,供其他模塊調用。
上面代碼表示新模塊返回一個對象,該對象的method方法就是外部調用的接口,menthod方法內部調用了m1模塊的methodA方法和m2模塊的methodB方法。
需要注意的是:回調函數必須返回一個對象,這個對象就是你定義的模塊。

如果依賴的模塊很多,參數與模塊一一對應的寫法非常麻煩。RequireJS提供一種更簡單的寫法。

define(
    function (require) {
        var dep1 = require('dep1'),
            dep2 = require('dep2'),
            dep3 = require('dep3'),
            dep4 = require('dep4'),
            dep5 = require('dep5'),
            dep6 = require('dep6'),
            dep7 = require('dep7'),
            dep8 = require('dep8');
            ...
    }
});

Demo:通過判斷瀏覽器是否爲IE,而選擇加載zepto或jQuery。

define(('__proto__' in {} ? ['zepto'] : ['jquery']), function($) {
    return $;
});

IE瀏覽器不支持proto屬性

require方法:調用模塊

require方法用於調用模塊。它的參數與define方法類似。

require(['foo', 'bar'], function ( foo, bar ) {
        foo.doSomething();
});

上面方法表示加載foo和bar兩個模塊,當這兩個模塊都加載成功後,執行一個回調函數。該回調函數就用來完成具體的任務。
require方法的第一個參數,是一個表示依賴關係的數組。
require方法也可以用在define方法內部。
動態加載模塊:

define(function ( require ) {
    var isReady = false, foobar;
    require(['foo', 'bar'], function (foo, bar) {
        isReady = true;
        foobar = foo() + bar();
    });

    return {
        isReady: isReady,
        foobar: foobar
    };
});

上面代碼所定義的模塊,內部加載了foo和bar兩個模塊,在沒有加載完成前,isReady屬性值爲false,加載完成後就變成了true。因此,可以根據isReady屬性的值,決定下一步的動作。

服務器端採用JSONP模式

如果服務器端採用JSONP模式,則可以直接在require中調用,方法是指定JSONP的callback參數爲define。

require( [ 
    "http://someapi.com/foo?callback=define"
], function (data) {
    console.log(data);
});

require方法允許添加第三個參數,即錯誤處理的回調函數。

require(
    [ "backbone" ], 
    function ( Backbone ) {
        return Backbone.View.extend({ /* ... */ });
    }, 
    function (err) {
        // ...
    }
);

require方法的第三個參數,即處理錯誤的回調函數,接受一個error對象作爲參數。
require對象還允許指定一個全局性的Error事件的監聽函數。所有沒有被上面的方法捕獲的錯誤,都會被觸發這個監聽函數。

requirejs.onError = function (err) {
    // ...
};

小結

define和require這兩個定義模塊、調用模塊的方法,合稱爲AMD模式。它的模塊定義的方法非常清晰,不會污染全局環境,能夠清楚地顯示依賴關係。
AMD模式可以用於瀏覽器環境,並且允許非同步加載模塊,也可以根據需要動態加載模塊。

配置require.js:config方法

require方法本身也是一個對象,它帶有一個config方法,用來配置require.js運行參數。config方法接受一個對象作爲參數。
config方法的參數對象有以下主要成員:
- baseUrl :指定本地模塊位置的基準目錄,即本地模塊的路徑是相對於哪個目錄的。該屬性通常由require.js加載時的data-main屬性指定。
- paths : path映射那些不直接放置於baseUrl下的模塊名。設置path時起始位置是相對於baseUrl的,除非該path設置以”/”開頭或含有URL協議(如http:)。
paths參數指定各個模塊的位置。這個位置可以是同一個服務器上的相對位置,也可以是外部網址。可以爲每個模塊定義多個位置,如果第一個位置加載失敗,則加載第二個位置,上面的示例就表示如果CDN加載失敗,則加載服務器上的備用腳本。需要注意的是,指定本地文件路徑時,可以省略文件最後的js後綴名。

 require.config({
    baseUrl: "/another/path",
    paths: {
        "some": "some/v1.0"
    }
  });
  require( ["some/module", "my/module", "a.js", "b.js"],
    function(someModule,myModule){
    }
  );

“my/module”的標籤src值是”/another/path/my/module.js”。當加載純.js文件(依賴字串以/開頭,或者以.js結尾,或者含有協議),不會使用baseUrl。因此a.js及b.js都在包含上述代碼段的HTML頁面的同目錄下加載。
注意:如未顯式設置baseUrl,則默認值是加載require.js的HTML所處的位置。如果用了data-main屬性,則該路徑就變成baseUrl。
在上述的配置下,”some/module”的script標籤src值是:

"/another/path/some/v1.0/module.js"
  • shim
    有些庫不是AMD兼容的,這時就需要指定shim屬性的值。shim可以理解成“墊片”,用來幫助require.js加載非AMD規範的庫。
require.config({
    paths: {
        "backbone": "vendor/backbone",
        "underscore": "vendor/underscore"
    },
    shim: {
        "backbone": {
            deps: [ "underscore" ],
            exports: "Backbone"
        },
        "underscore": {
            exports: "_"
        }
    }
});

上面代碼中的backbone和underscore就是非AMD規範的庫。shim指定它們的依賴關係(backbone依賴於underscore),以及輸出符號(backbone爲“Backbone”,underscore爲“_”)。

優化器r.js

RequireJS提供一個基於node.js的命令行工具r.js,用來壓縮多個js文件。它的主要作用是將多個模塊文件壓縮合併成一個腳本文件,以減少網頁的HTTP請求數。
第一步是安裝r.js(假設已經安裝了node.js)。

npm install -g requirejs

然後,使用的時候,直接在命令行鍵入以下格式的命令。

node r.js -o <arguments>

arguments表示命令運行時,所需要的一系列參數,比如像下面這樣:

node r.js -o baseUrl=. name=main out=main-built.js

除了直接在命令行提供參數設置,也可以將參數寫入一個文件,假定文件名爲build.js。

({
    baseUrl: ".",
    name: "main",
    out: "main-built.js"
})

然後,在命令行下用r.js運行這個參數文件,就OK了,不需要其他步驟了。

node r.js -o build.js

參數文件的範例

假定位置就在根目錄下,文件名爲build.js。

({
    appDir: './',
    baseUrl: './js',
    dir: './dist',
    modules: [
        {
            name: 'main'
        }
    ],
    fileExclusionRegExp: /^(r|build)\.js$/,
    optimizeCss: 'standard',
    removeCombined: true,
    paths: {
        jquery: 'lib/jquery',
        underscore: 'lib/underscore',
        backbone: 'lib/backbone/backbone',
        backboneLocalstorage: 'lib/backbone/backbone.localStorage',
        text: 'lib/require/text'
    },
    shim: {
        underscore: {
            exports: '_'
        },
        backbone: {
            deps: [
                'underscore',
                'jquery'
            ],
            exports: 'Backbone'
        },
        backboneLocalstorage: {
            deps: ['backbone'],
            exports: 'Store'
        }
    }
})

上面代碼將多個模塊壓縮合併成一個main.js。

參數文件的主要成員解釋如下:

  • appDir:項目目錄,相對於參數文件的位置。
  • baseUrl:js文件的位置。
  • dir:輸出目錄。
  • modules:一個包含對象的數組,每個對象就是一個要被優化的模塊。
  • fileExclusionRegExp:凡是匹配這個正則表達式的文件名,都不會被拷貝到輸出目錄。
  • optimizeCss: 自動壓縮CSS文件,可取的值包括“none”, “standard”, “standard.keepLines”, “standard.keepComments”, “standard.keepComments.keepLines”。
  • removeCombined:如果爲true,合併後的原文件將不保留在輸出目錄中。
  • paths:各個模塊的相對路徑,可以省略js後綴名。
  • shim:配置依賴性關係。如果某一個模塊不是AMD模式定義的,就可以用shim屬性指定模塊的依賴性關係和輸出值。
  • generateSourceMaps:是否要生成source map文件。
    更詳細的解釋可以參考官方文檔
    運行優化命令後,可以前往dist目錄查看優化後的文件。
    另一個build.js的例子:
({
    mainConfigFile : "js/main.js",
    baseUrl: "js",
    removeCombined: true,
    findNestedDependencies: true,
    dir: "dist",
    modules: [
        {
            name: "main",
            exclude: [
                "infrastructure"
            ]
        },
        {
            name: "infrastructure"
        }
    ]
})

上面代碼將模塊文件壓縮合併成兩個文件,第一個是main.js(指定排除infrastructure.js),第二個則是infrastructure.js。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章