前端模塊化的演變過程


隨着前端的發展,無模塊化存在的問題日益顯露。但在這個過程中,模塊化也是有一定的發展。

stage1-文件划分方式

根據業務或功能封裝某一類變量或者函數;

約定每一個文件都是一個模塊;

當使用到這個模塊的時候,通過script標簽引入到html頁面中,直接使用模塊中的成員(變量|函數);

但當代碼體積達到一定量的時候,這種方法的缺點就很明顯了。 

//module-a.js 

var name = 'module-a'

function method1 () {
  console.log(name + '#method1')
}

function method2 () {
  console.log(name + '#method2')
}
//module-b.js 

var name = 'module-b'

function method1 () {
  console.log(name + '#method1')
}

function method2 () {
  console.log(name + '#method2')
}
//index.html
  <script src="module-a.js"></script>
  <script src="module-b.js"></script>
  <script>
    // 命名沖突
    method1()
    // 模塊成員可以被修改
    name = 'foo'
  </script>

缺點:

  1. 全部變量都暴露在全局作用域中,沒有私有空間,所有成員都可被外部訪問或者修改
  2. 當模塊達到一定數量,通過約定的方式很難避免變量沖突
  3. 無法管理模塊與模塊之間的依賴關系

stage2-命名空間的方式

每個模塊只暴露一個全局對象,所有的成員都掛載到這個全局對象上

//module-a.js
var moduleA = {
  name: 'module-a',

  method1: function () {
    console.log(this.name + '#method1')
  },

  method2: function () {
    console.log(this.name + '#method2')
  }
}
//module-b.js
var moduleB = {
  name: 'module-b',

  method1: function () {
    console.log(this.name + '#method1')
  },

  method2: function () {
    console.log(this.name + '#method2')
  }
}
//index.html
  <script src="module-a.js"></script>
  <script src="module-b.js"></script>
  <script>
    moduleA.method1()
    moduleB.method1()
    // 模塊成員可以被修改
    moduleA.name = 'foo'
  </script>

優點:

通過“命名空間”減小了命名沖突的可能

缺點:

模塊內部的成員依然在外部可以被訪問和修改

模塊之間的依賴關系依然不明確

stage3-通過立即執行函數(IIFE)為模塊提供私有空間

具體做法就是將模塊內的代碼放在一個立即執行函數中

若想把某個成員暴露出去,就把該成員掛載到window中

//module-a.js
;(function () {
  var name = 'module-a'
  
  function method1 () {
    console.log(name + '#method1')
  }
  
  function method2 () {
    console.log(name + '#method2')
  }

  window.moduleA = {
    method1: method1,
    method2: method2
  }
})()
//module-b.js
;(function ($) {
  var name = 'module-b'
  
  function method1 () {
    console.log(name + '#method1')
  }
  
  function method2 () {
    console.log(name + '#method2')
  }

  window.moduleB = {
    method1: method1,
    method2: method2
  }
  console.log($('#a').html());
})(jQuery)
//index.html
 <script src="module-a.js"></script>
  <script src="module-b.js"></script>
  <script>
    moduleA.method1()
    moduleB.method1()
    // 模塊私有成員無法訪問
    console.log(moduleA.name) // => undefined
  </script>

優點:

實現了成員私有化,模塊內的變量外界不能隨意訪問

通過立即執行函數,可以傳遞該模塊所依賴的模塊,使模塊對外部的依賴更加清晰

小結:綜上所述,隨着模塊化的發展,之前所提到的問題也逐一被解決,但還是存在一部分沒有解決的問題。先前所有模塊都是通過script標簽引入的。若我們需要某個模塊時,通過script標簽引入了該模塊,但可能會忘記引入該模塊所依賴的模塊。或者當我們刪除某個模塊時,我們也可能會忘記該模塊所依賴的模塊。

stage4-模塊化規范的出現

1.CommonJS

​ 特點:

1.一個文件就是一個模塊

​ 2.每個模塊都有一個單獨的作用域

   3.每個模塊暴露出去的成員都由module.exports導出

​ 4.使用其他模塊的成員時使用require函數導入

​ CommonJS規范主要引用在Node項目中,該規范加載模塊時同步加載,倘若用在瀏覽器中,會有大量的同步請求導致應用比較慢,但在Node中不會有問題(因為Node是啟動時加載模塊)

2.AMD規范(Asynchronous Module Definition

​ 代表庫:require.js

​ 特點:

​ 不同於CommonJS的同步加載,該模塊可以異步加載模塊,提高程序在瀏覽器的執行效率

​ 但使用起來相對復雜

3.CMD規范( Common Module Definition )

​ 代表庫:Sea.js

​ 特點:

​ 使用上類似於require.js,寫法類似於CommonJS,算是個重復的輪子

4.ES Modules(ES2015的新語法)

​ 特點:

​ 語言層面推出的新語法,比較完善

​ 滿足在web端開發使用模塊化的需求

綜上所述:目前前端模塊化基本統一成了CommonJS(Node.js)和ES Modules(瀏覽器端開發),我們只需掌握這兩種規范開發即可,后續會對着兩個模塊重點展開討論


免責聲明!

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



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