模塊化是指將一個複雜的系統分解爲多個模塊,方便編碼,同時下降代碼複雜性,下降代碼耦合度,方便部署,提升效率,避免了命名衝突,也能夠減小變量空間污染,更好的分離代碼,方便按需加載,更高的複用性,更高的可維護性。常見的模塊化有CommonJs、AMD、CMD、ES6
,下面就分別來介紹他們。html
CommonJs
CommonJs
將每一個javaScript
文件看成是一個模塊, 其內部定義的變量函數等都屬於這個模塊,咱們能夠向外部暴露咱們想要暴露的。可是CommonJs
必須在node
環境下才能使用,它是爲node
而生的,只有使用node環境才能運行,而瀏覽器是不支持CommonJs
的,必須使用一些轉換工具,將咱們服務器端的CommonJs
語法轉化爲瀏覽器識別的語法。java
在CommonJs
中,每個javaScript
文件都會隱士的被包裹在一個當即函數裏面,例以下面的例子node
var name = 'xxx' module.exports = { name: name }
最終會被轉換成下面這個樣子api
(function(exports, require, module, __filename, __dirname){ var name = 'xxx' module.export = { name: name } })
exports、 require、 module、 __filename、 __dirname
exports
和module.exports
實際上是一個東西,只不過須要注意使用exports
不能改變它的指向。require
是用來引入咱們須要的外部模塊的,他是同步加載的,適用於服務器端。__filename
和__dirname
分別是當前執行的文件路徑和文件夾路徑。瀏覽器
CommonJs
通常咱們能夠直接使用node 文件名
直接將文件置於node環境運行,這樣是徹底ok的。可是假若咱們須要將它放到瀏覽器端運行,也就是引入到html
文件中,因爲瀏覽器是不認識前面咱們說的exports、require...
這些語法的,因此咱們能夠藉助像Browserify
這樣的轉換工具。咱們看下面的例子服務器
// m1.js module.exports = { name: 'xxx' } // m2.js module.exports = { age: '100' } // main.js const name = require('m1') const age = require('m2') console.log(name, age) // index.html ... <script src="./node_modules/main.js"></script> ...
當咱們打開html的時候瀏覽器是會報錯的,以下babel
Uncaught ReferenceError: require is not defined at main.js:1
咱們能夠藉助Browserify,將Browserify
下載下來,將咱們的main.js
使用它轉換後,將轉換後的文件引入頁面中,修改後咱們就能正常運行了,修改後的html代碼以下網絡
<script src="./node_modules/bundle.js"></script>
browerify
用法很簡單,能夠看它的文檔異步
AMD
CommonJs
爲服務器端而生,採用的同步加載方式。所以不適用瀏覽器。由於瀏覽器須要到服務器加載文件,請求時間遠大於本機讀取的時間,假若文件較多,網絡遲緩就會致使頁面癱瘓,因此瀏覽器更但願可以時間異步加載的方式。
而AMD
規範則是異步加載模塊,容許指定回調函數。等模塊異步加載完成後便可調用回調函數。它依賴一個庫require.js,這裏就簡單的說一下它的用法,具體請參考文檔。AMD
的核心思想就是經過define
來定義一個模塊,而後使用require
來加載一個模塊。
``async
define
基本使用define(moduleId,['module1','mdule2'],function(m1,m 2){...});
moduleId
爲當前定義的模塊ID,若是不寫默認是當前文件名,module1
等是咱們要引入的模塊的ID
,func
的參數就是導入的模塊例如m1
就是module1
導入的變量,以後咱們使用m1
就行,須要注意的是若是咱們要像module.exports
同樣向外暴露變量等,咱們須要在每一個模塊的func
中返回咱們須要暴露的東西
require
在咱們須要定義模塊的地方使用define,當咱們須要使用這些暴露的模塊的時候,使用require(['module1','module2'],function(m1, m2) {...})
在func
中寫咱們的代碼
同時須要在最上面配置一下咱們須要引入的模塊的路徑以及它涉及到的模塊的路徑使用require.config({paths: { 模塊一: 路徑,模塊二: 路徑}})
下面給一個簡單的AMD例子
// m1.js define(function() { return { name: 'xxx' } }); // m2.js define(function() { return { age: '100' } }); // main.js require.config({ path: { m1: './m1.js', m2: './m2.js' } }) require(['m1', 'm2'], function (m1, m2) { console.log(m1.name, m2.age) }) // index.html ... <script src="./node_modules/require.js" data-main="./node_modules/main.js"></script> ...
CMD
CMD
異步加載,跟AMD
的主要區別在於,AMD
依賴前置,提早加載依賴。而CMD
就近加載,按需加載。
產物seaJs,跟requireJs
使用有些類似。
若是咱們想使用SeaJS
,咱們只須要將其引入到咱們的頁面中,而後使用seajs.use('入口文件')
,咱們就能夠在咱們的入口文件中使用咱們的CMD
了CMD
的核心思想就是經過define
來定義一個模塊,而後使用require
來加載一個模塊,聽起來和AMD
有點相似,可是實際的使用仍是有區別的。
define
當咱們在一個文件中定義一個模塊的時候,能夠像下面這樣
define(function(require,exports,module){ module.exports = {} })
require
require
在CMD
中分爲同步和異步下面分別給出同步和異步使用的方式
// 同步 var module = require('xxx') //異步 var module = require.async('m1', function(m1){ ... })
ES6
ES6
自帶模塊化,可使用 import
關鍵字引入模塊,經過 export
關鍵字導出模塊,功能較之於前幾個方案更爲強大,也是咱們所推崇的,可是因爲ES6
目前沒法在瀏覽器中執行,因此,咱們只能經過babel
將不被支持的import
編譯爲當前受到普遍支持的 require
。