前端模塊化CommomJs、AMD、CMD以及ES6的import詳解

模塊化

模塊化是指將一個複雜的系統分解爲多個模塊,方便編碼,同時下降代碼複雜性,下降代碼耦合度,方便部署,提升效率,避免了命名衝突,也能夠減小變量空間污染,更好的分離代碼,方便按需加載,更高的複用性,更高的可維護性。常見的模塊化有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

exportsmodule.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等是咱們要引入的模塊的IDfunc的參數就是導入的模塊例如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

requireCMD中分爲同步和異步下面分別給出同步和異步使用的方式

// 同步
var module = require('xxx')
//異步
var module = require.async('m1', function(m1){
...
})

ES6

ES6自帶模塊化,可使用 import 關鍵字引入模塊,經過 export 關鍵字導出模塊,功能較之於前幾個方案更爲強大,也是咱們所推崇的,可是因爲ES6目前沒法在瀏覽器中執行,因此,咱們只能經過babel將不被支持的import編譯爲當前受到普遍支持的 require

相關文章
相關標籤/搜索