在上一篇js模塊化入門與commonjs解析與應用中詳細的解析了關於commonjs模塊化規範,commonjs採用的用同步加載方式,這致使它並非瀏覽器理想的模塊化規範。由於瀏覽器須要到服務器加載文件,請求事件遠遠大於本機讀取的時間,若是文件較多,網絡遲緩就會致使頁面癱瘓,因此瀏覽器更但願可以實現異步加載的方式。css
AMD規範則是異步加載模塊,用於指定回調函數。等模塊加載完成之後便可調用回調函數。AMD規範得意的產出就是require.js。html
先經過示例來感覺如下AMD規範實現的requirejs的應用:jquery
1.1定義工做區間文件結構webpack
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):web
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):api
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官方都給出解決方案,能夠參考這篇博客:http://www.javashuo.com/article/p-wgendvdq-dh.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
在上面一節介紹了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自帶模塊化,可使用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須要考慮異步隊列的執行順序問題,因此這裏的更好和更優要相對而言。
(後續深刻研究後再來補充)