js模塊化

 

es6

定義了新的模塊標準化,提供了moduleshtml

export xxx;
import xxx from file

 

沒有采用nodejs的CommonJS,前端

沒有實現require,node

require和module.exports只是node的私有全局方法和對象屬性jquery

 

建議寫法:webpack

export {fun as default,a,b,c};git

 

nodejs

模塊的規範是CommonJS

module.exports = data;
var data = require(file)

 

commonjs 對應 瀏覽器,nodejs的概念位置es6

 

  |---------------瀏覽器----- ------------------|        |--------------------------CommonJS----------------------------------|github

  |  BOM  |       | DOM |        | ECMAScript |         | FS |           | TCP |         | Stream |        | Buffer |          |........|web

  |-------W3C-----------|       |---------------------------------------Node--------------------------------------------------|api

 

 

CommonJS 是同步加載模塊

var math = require('math'); //(同步) math.js 引去進來後,纔會執行後面的add,文件都在磁盤上,同步沒有任何問題

math.add(2,3); // 5

 

瀏覽器也能用

其爲nodejs專有,因爲瀏覽器沒有全局變量module、require等,不過能夠藉助一些工具完成瀏覽器端的實現,

其原理是現將全部模塊都定義好並經過 id 索引,這樣就能夠方便的在瀏覽器環境中解析了,

如:Browserify

// foo.js
module.exports = function(x) {
  console.log(x);
};
 
// main.js
var foo = require("./foo");
foo("Hi");
.js > compiled.js$ browserify main
-unpack < compiled.js$ browser
 
[
  {
    "id":1,
    "source":"module.exports = function(x) {\n  console.log(x);\n};",
    "deps":{}
  },
  {
    "id":2,
    "source":"var foo = require(\"./foo\");\nfoo(\"Hi\");",
    "deps":{"./foo":1},
    "entry":true
  }
]
 

執行的時候,瀏覽器遇到 require('./foo') 語句,就自動執行1號模塊的 source 屬性,並將執行後的 module.exports 屬性值輸出。

 

CommonJS 已通過時,Node.js 的內核開發者已經廢棄了該規範

 

 

如今用了webpack和babel編譯

es6的import 是編譯時的,選擇import的內容編譯進來,性能更好

commonjs的require是運行時的,運行的時候,會執行require 模塊後賦值給某個變量

 

目前無論是nodejs中,仍是寫前端代碼,爲了支持es6都是用babel編譯,babel實際上是把把es6轉成es5,import編譯成require,

因此用babel編譯的代碼能夠混搭 import和require

 

瀏覽器端

爲何commonjs 不適合

CommonJS 是同步加載模塊

var math = require('math'); //(同步) 等待math.js 引去進來後,纔會執行後面的add,文件都在磁盤上,同步沒有任何問題
math.add(2,3); // 5

 

這時候瀏覽器端不適合的,js是經過網絡加載的,由於模塊都放在服務器端,等待時間取決於網速的快慢,可能要等很長時間,瀏覽器處於"假死"狀態。

 

所以,瀏覽器端的模塊,不能採用"同步加載"(synchronous),只能採用"異步加載"(asynchronous)。這就是AMD規範誕生的背景。

AMD是"Asynchronous Module Definition"的縮寫

它採用異步方式加載模塊,模塊的加載不影響它後面語句的運行。全部依賴這個模塊的語句,都定義在一個回調函數中,等到加載完成以後,這個回調函數纔會運行

 

require(['math'], function (math) {
    math.add(2, 3);// math 加載好了後執行這句
  });

 

math.add()與math模塊加載不是同步的,瀏覽器不會發生假死。

說白了,js的執行沒有提升和改變,主要是不想讓加載js影響到代碼;因此須要咱們換種回調類型的寫法,加載好了經過回調執行js,沒有誰會由於加載而卡住。

 

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

最先的時候,全部Javascript代碼都寫在一個文件裏面,只要加載這一個文件就夠了。後來,代碼愈來愈多,一個文件不夠了,必須分紅多個文件,依次加載。下面的網頁代碼,相信不少人都見過。

 

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

這段代碼依次加載多個js文件。

 

這樣的寫法有很大的缺點。首先,加載的時候,瀏覽器會中止網頁渲染,加載文件越多,網頁失去響應的時間就會越長;其次,因爲js文件之間存在依賴關係,所以必須嚴格保證加載順序(好比上例的1.js要在2.js的前面),依賴性最大的模塊必定要放到最後加載,當依賴關係很複雜的時候,代碼的編寫和維護都會變得困難。

 

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

  (1)實現js文件的異步加載,避免網頁失去響應;

  (2)管理模塊之間的依賴性,便於代碼的編寫和維護。

 

瀏覽器目前模塊化方式

瀏覽器端有requirejs(AMD)和seajs(CMD)之類的工具包實現模塊化,他們寫法差很少,執行原理過程有點區別,後面會說

// ----------- AMD or CMD ----------------
define(function(require, exports, module){
  module.exports = {
    a : function() {},
    b : 'xxx'
  };
});


// ------------ AMD or CMD -------------
define(function(require, exports, module){
   var m = require('./a');
   m.a();
});

 

 

AMD(異步模塊定義)主要爲前端js的表現指定規範

define(id?: String, dependencies?: String[], factory: Function|Object);

 

id 是模塊的名字,它是可選的參數。

dependencies 指定了所要依賴的模塊列表,它是一個數組,也是可選的參數,每一個依賴的模塊的輸出將做爲參數一次傳入 factory 中。若是沒有指定 dependencies,那麼它的默認值是 ["require", "exports", "module"]

define(function(require, exports, module) {})

factory 是最後一個參數,它包裹了模塊的具體實現,它是一個函數或者對象。若是是函數,那麼它的返回值就是模塊的輸出接口或值。

eg:

定義一個名爲 myModule 的模塊,它依賴 jQuery 模塊:

define('myModule', ['jquery'], function($) {
    // $ 是 jquery 模塊的輸出
    $('body').text('hello world');
});
// 使用
define(['myModule'], function(myModule) {});

 

在模塊定義內部引用依賴:

define(function(require) {
    var $ = require('jquery');
    $('body').text('hello world');
});

這裏有define,把東西包裝起來啦,那require.js 和 Node實現中怎麼沒看到有define關鍵字呢,它也要把東西包裝起來呀,其實吧,只是他們隱式包裝了而已

 

SeaJs和RequireJs區別

SeaJS對模塊的態度是懶執行, 而RequireJS對模塊的態度是預執行

以下模塊經過SeaJS/RequireJS來加載, 執行結果會是怎樣?

define(function(require, exports, module) {
    console.log('require module: main');

    var mod1 = require('./mod1');
    mod1.hello();
    var mod2 = require('./mod2');
    mod2.hello();

    return {
        hello: function() {
            console.log('hello main');
        }
    };
});
 

 

先試試SeaJS的執行結果,他是須要的時候執行依賴

    require module: main

    require module: mod1

    hello mod1

    require module: mod2

    hello mod2

    hello main

 

 

再來是RequireJS的執行結果,他是 全部的依賴提早執行好了,

    require module: mod1

    require module: mod2

    require module: main

    hello mod1

    hello mod2

    hello main

 

 

 

參考: 

AMD http://www.cnblogs.com/chenguangliang/p/5856701.html

Commonjs http://www.cnblogs.com/skylar/p/4065455.html

相關文章
相關標籤/搜索