程式碼:https://github.com/zhengyeye/JS-modularity
什麼是模組、模組化?
將一個複雜的程式依據一定的規則(規範)封裝成幾個塊(檔案), 並進行組合在一起;
塊的內部資料/實現是私有的, 只是向外部暴露一些介面(方法)與外部其它模組通訊。
為什麼要模組化?
當專案功能越來越多,程式碼量便也會越來越多,後期的維護難度會增大,此時在JS方面就會考慮使用模組化規範去管理,想要什麼功能,就載入什麼模組,但前提是大家在編寫程式碼時需要使用同一規範。
現在最流行的模組化規範有:CommonJs,、AMD、CMD、以及ES6。
模組化的好處:
1.避免命名衝突(減少名稱空間汙染);
2.更好的分離, 按需載入;
3.更高複用性;
4.高可維護性。
CommonJS規範
1.在伺服器端: 模組的載入是執行時同步載入的;
2.在瀏覽器端: 模組需要提前編譯打包處理;
CommonJS是Node.js使用的模組化標準。在CommonJS中,有一個全域性性方法require(),用於載入模組。
基本語法:
暴露模組:(本質都是暴露exports這個物件,module.exprots={}就是一個空物件)
①module.exports = value;
②exports.xxx = value;
引入模組:
1 require(xxx); //第三方模組:xxx為模組名 2 //自定義模組: xxx為模組檔案路徑
1 //檔案A 2 module.exports = {...} 3 .... 4 5 //檔案B 6 var a = require('./foo/bar')
實現方式:
①伺服器端:Node.js;
app.js為主入口檔案,使用命令列:node app.js便可啟起服務,看到控制檯列印的資料;
②瀏覽器端:Browserify(也稱為CommonJS的瀏覽器端的打包工具);
兩者區別:①Node.js執行時動態載入模組(同步);②Browserify是在轉譯(編譯)時就會載入打包(合併)require的模組。
index.html為主入口檔案,在瀏覽器中開啟此頁面,正常執行便可看到控制檯列印的資料;但是,這樣去報錯了:
Uncaught ReferenceError: require is not defined
at app.js:9
瀏覽器並不認識app.js中的方法,因此便需要將app.js編譯打包處理成為它所能識別的檔案,於是在專案根目錄下使用命令列:
browserify js/src/app.js -o js/dist/bundle.js
這句話的意思就是找到js/src/app.js檔案,並將它-o:output 輸出為 js/dist/bundle.js,這樣再在index.html中引入bundle.js檔案後,便可(dist資料夾可以為空,也可以讓其自行建立)。
AMD規範(Asynchronous Module Definition(非同步模組定義))
1.AMD:專門用於瀏覽器端, 模組的載入是非同步的;
基本語法:
①定義暴露模組
1 //定義沒有依賴的模組 2 define(function(){ 3 return 模組 4 })
1 //定義有依賴的模組 2 define(['module1', 'module2'], function(m1, m2){ 3 return 模組 4 })
②引入使用模組:
1 require(['module1', 'module2'], function(m1, m2){ 2 使用m1/m2 3 })
實現方式:
瀏覽器端:Require.js
CMD規範( Common Module Definition(通用模組定義))
1.CMD:專門用於瀏覽器端, 模組的載入是非同步的;
2.專門用於瀏覽器端, 模組的載入是非同步的 ;
3.模組使用時才會載入執行;
4.較其他使用次數少。
基本語法:
①定義暴露模組:類似於CommonJS
1 //定義沒有依賴的模組 2 define(function(require, exports, module){ 3 exports.xxx = value 4 module.exports = value 5 })
1 //定義有依賴的模組 2 define(function(require, exports, module){ 3 //引入依賴模組(同步) 4 var module2 = require('./module2') 5 //引入依賴模組(非同步) 6 require.async('./module3', function (m3) { 7 8 }) 9 //暴露模組 10 exports.xxx = value 11 })
②引入使用模組
1 define(function (require) { 2 var m1 = require('./module1') 3 var m4 = require('./module4') 4 m1.show() 5 m4.show() 6 })
實現方式:
瀏覽器端:Sea.js
CMD:不嚴謹的講,其實就是集合commonjs+AMD的特點。
ES6
目前主流規範。AMD與CMD均比較commonjs繁瑣,而es6最簡潔。
1.ES6;
2.依賴模組需要編譯打包處理(部分瀏覽器不支援);
語法:
①匯出模組: export
②引入模組: import
實現方式:
瀏覽器端:
①使用Babel將ES6編譯為ES5程式碼;
②使用Browserify編譯打包js。
在index.html中使用(在html中引入的js檔案必須為編譯過後的檔案):
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <!-- <script type="text/javascript" src="js/src/app.js"></script> --> 9 <script type="text/javascript" src="js/lib/bundle.js"></script> 10 </body> 11 </html>