js模塊化AMD、CMD、ES6


  • AMD
  • CMD
  • ES6模塊化
  • 各個模塊化規范對比理解

 一、AMD

在上一篇js模塊化入門與commonjs解析與應用中詳細的解析了關於commonjs模塊化規范,commonjs采用的用同步加載方式,這導致它並不是瀏覽器理想的模塊化規范。因為瀏覽器需要到服務器加載文件,請求事件遠遠大於本機讀取的時間,如果文件較多,網絡遲緩就會導致頁面癱瘓,所以瀏覽器更希望能夠實現異步加載的方式。

AMD規范則是異步加載模塊,用於指定回調函數。等模塊加載完成以后即可調用回調函數。AMD規范得意的產出就是require.js。

https://requirejs.org/

先通過示例來感受以下AMD規范實現的requirejs的應用:

1.1定義工作區間文件結構

1 cmd//工作區間
2     modules-->依賴模塊
3         m1.js-->模塊1
4         m2.js-->模塊2
5     demo.html-->結構文本
6     demo.js-->js主入口文件
7     require.js-->CMD模塊化工具

1.2.1依賴模塊代碼(m1):

1 define(function (){
2    var name = 'm1-amd';
3    function getName(){
4        return name;
5      }
6      return {getName};//{getName}同等與{getName:getName} 
7 })

1.2.2依賴模塊代碼(m2):

1 define(['m1'],function(m1){
2     var msg = 'm2-amd';
3     function show(){
4         console.log(msg,m1.getName());
5     }
6     return {show};
7 })

1.3JS主入口文件:

 1 (function (){
 2     require.config({
 3         paths:{
 4             m2:'./modules/m2',
 5             m1:'./modules/m1'
 6         }
 7     });
 8     require(['m2','jquery'],function(m2,$){
 9         m2.show();
10     });
11 })();

1.4在結構文本中引入AMD規范模塊化處理工具require.js,並將主入口文件通過自定義屬性data-main='主入口文件路徑'的方式引入工具中進行處理:

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

AMD的基本規范的全稱“Asynchronous Module Definition”的縮寫,意思是“異步加載模塊”。它采用異步方式加載模塊,模塊的加載不影響后面語句的運行。所有依賴這個模塊的語句,都定義在一個回調函數中,等到加載完成后,這個回調函數才會運行。

 

AMD規范實際上是requirejs項目在推廣過程中形成的一個產物,先來看看requirejs的基本使用:

  requirejs模塊定義:define(id?,dependencies?,factory);==>id:可選參數,用來定義模塊的標識,如果沒有提供該參數,模塊標識就取腳本文件名(去掉擴展名)。==>dependencies:用來傳入當前模塊依賴的模塊名稱數組。==>factory:工廠方法,模塊初始化要執行的函數或對象,如果是函數,它只被執行一次。如果是對象,此對象應該為模塊的輸出值。

  requirejs模塊主入口(模塊加載):require.config({paths:{foo:'路徑'}});==>faths:配置所有依賴模塊的路徑。在路徑配置代碼的下方,再通過require(dependencies?,factory)定義主入口文件的依賴關系和回調函數。

 

在requirejs中還可以實現依賴其他庫和插件,有些插件和庫定義了requirejs的標准接口,比如jQuery,但是有些沒有標准接口,requirejs官方都給出解決方案,可以參考這篇博客:https://www.cnblogs.com/goloving/p/7711104.html。例如我在示例中也測試了jQuery的使用:

 1 (function (){
 2     require.config({
 3         paths:{
 4             m2:'./modules/m2',
 5             m1:'./modules/m1',
 6             jquery:'./jquery-2.0.3'
 7         }
 8     });
 9     require(['m2','jquery'],function(m2,$){
10         m2.show();
11         $('body').css('backgroundColor','#000');
12     });
13 })();

關於requirejs更多API可以查看官網的API示例:https://requirejs.org/docs/api.html

 二、CMD

 在上面一節介紹了AMD規范以及規范實現的requirejs的基本使用,其中提到了AMD相對於Commonjs的優勢在於異步加載模塊,但是我沒由說明這個異步加載在什么時候觸發,到了CMD這里有必要提一下了,AMD規范很重要的一個思想就是依賴前置,意思就是在模塊執行前將所有依賴的模塊先全部加載到本地。而CMD的加載方式也是異步加載,但是觸發加載的時間是在需要某個依賴模塊時再去加載,也有人將CMD說成是同步的,這種同步並不是表現在資源加載上,而是觸發加載的指令與代碼執行是同步的,資源加載還是異步加載模式。

關於Commonjs、AMD、CMD、ES6模塊化的異同在最后會由詳細的對比分析。

 

2.1.先來看CMD的基本應用:https://www.zhangxinxu.com/sp/seajs/

2.1.1.定義工作區間文件結構

CMD//工作區間
    -->modules//依賴模塊
        -->m1.js
        -->m2.js
        -->m3.js
        -->m4.js
    dome.html//結構文本
    demo.js//JS主入入口文件
    sea.js//模塊化工具

2.1.2.m1模塊代碼

1 define(function(require,exports,module){
2     var msg = 'm1';
3     function foo(){
4         console.log(msg);
5     }
6     module.exports = {
7         foo:foo
8     }
9 })

2.1.3.m2模塊代碼

1 define(function(require,exports,module){
2     var msg = 'm2';
3     function bar(){
4         console.log(msg);
5     }
6     module.exports = bar;
7 })

2.1.4.m3模塊代碼

1 define(function(require,exports,module){
2     var msg = 'm3';
3     function foo(){
4         console.log(msg);
5     }
6     exports.foo = foo;
7 })

2.1.5.m4模塊代碼

 1 define(function(require,exports,module){
 2     var msg = 'm4';
 3     // 同步加載
 4     var m2 = require('./m2');
 5     m2();
 6     // 異步加載
 7     require.async('./m3',function(m3){
 8         m3.foo();
 9     });
10     function fun(){
11         console.log(msg);
12     }
13     exports.fun = fun;
14 })

2.1.6.JS主入口文件demo代碼

1 define(function(require,exports,module){
2     var m1 = require('./modules/m1');
3     m1.foo();
4     var m4 = require('./modules/m4');
5     m4.fun();
6 })

2.1.7.結構文本demo.html引入模塊化處理工具sea.js,使用seajs工具對象方法user找到主入口文件並解析執行==>seajs.use('主入口文件路徑'):

1 <script src="./sea.js"></script>
2 <script>
3     seajs.use('./demo.js');
4 </script>

最后代碼打印結果:

這里值得我們關注的是m4打印在m3的前面,這就是CMD依賴就近原則產生的,在執行隊列中異步請求需要等主線程執行完成以后才會調用執行,所以m3作為異步加載模塊,在這個代碼結構中要最后執行。

值得我們注意的seajs也有同步加載模式直接使用require('模塊路徑')獲取模塊,異步模塊加載方式需要使用require.async('模塊路徑',function(模塊名稱){回調執行內容})。

 三、ES6模塊化

 ES6自帶模塊化,可以使用import關鍵字引入模塊,通過export關鍵字到處模塊,功能較之前幾個方案更為強大,但是由於ES6目前無法在瀏覽器中執行,所以,需要通過babel將不支持的import編譯為當前收到廣泛支持的require。

 1 //  引入默認變量及方法和模塊導入的m1 m2變量或方法
 2 import theDefault,{m1,m2} from 'lib';
 3 //  引入默認變量及方法
 4 import theDefault from 'lib';
 5 //  引入模塊導出的m1 m2變量或方法
 6 import {m1,m2} from 'lib';
 7 //  引入模塊導出的m1並且將m1重命名myName m2變量或者方法
 8 import * as myLib from 'lib';
 9 // 只將lib加載進來 沒有用來lib中暴露的接口
10 import 'lib';
11 
12 
13 //  暴露變量
14 export var a = '123';
15 //  暴露函數
16 export function myFun(){
17 
18 }
19 //  默認暴露變量函數等
20 export default a = '123';
21 export function myFun(){}

關於ES6的模塊化會在ES6的相關博客中來詳細解析,這里只做一些基本介紹。

 四、各個模塊化規范對比理解

1.什么是模塊化?

答:模塊化是指將一個復雜的系統分解為多個模塊,方便編碼。

2.為什么要用模塊化?

答:降低復雜性,降低代碼耦合度,部署方便,提高效率。

3.模塊化的好處?

答:3.1.避免命名沖突,減少變量空間污染;

  3.2.更好的分離代碼,按序加載;

  3.3.更高復用性;

  3.4.更高可維護性;

4.Webpack支持性:

AMD、ES Modules(推薦使用)、CommonJS因為webpack是基於nodeJS的,所以有必要了解學習。

 

5.AMD、CMD、CommonJS模塊規范的對比分析:

  AMD、CMD可以使用插件引入的方式實現JS代碼模塊化管理,CommonJS不兼容瀏覽器需要Browserify工具在nodejs環境下轉換成瀏覽器可執行的JS文件。

  Commonjs采用同步加載,會在一定程度上增加頁面載入時間,如果在這個過程中出現某個模塊錯誤,會導致頁面加載失敗。

  AMD、CMD采用異步加載,兩者的區別就是AMD采用前置預加載模式,CMD采用就近原則加載模式。AMD的體驗更好,CMD的性能更優,但是CMD需要考慮異步隊列的執行順序問題,所以這里的更好和更優要相對而言。

  (后續深入研究后再來補充)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM