前端模組化發展歷程 (-)

_skylar發表於2021-07-14

本文將從以下三點來做一個詳細講解:

  1. 模組化產生
  2. 早期模組化解決方案
  3. 模組化規範的產生和差異

模組化產生

在早期的前端開發中,並沒有模組的概念,模組只在服務端存在,用於處理複雜的業務通訊等。 直到 AJAX 被提出,前端能夠像後端請求資料,前端邏輯越來越複雜,就出現了許多問題:全域性變數,函式名衝突,依賴關係不好處理... 隨著業務邏輯的增加,對模組需求越來越大,所以才有了後續一系列 AMD、commonJS、ES6Module 規範。

早期模組化解決方案

兩種解決方法:

  • 匿名函式自呼叫(閉包): 形成私有變數; 棧記憶體處理 
  • 基於物件進行分組 堆記憶體處理; “單例模式思想” : 基於單獨的例項, 來實現資訊分組, 避免全域性變數的汙染

下面一個簡單的例子

// 新聞板塊
let newMOdel = (function(){
  let time = new  Date()
  const query = function query() {}
  const handle = function handel() {}
  return {
    query,
    handle
  }
}())
// 皮膚板塊
let skinModel = (function() {
  let time = '2021-07-05'
  const hanle = function handel(){ }
  newMOdel.query()
}())

最早期的模組程式設計思想就是這種 高階單例設計模「閉包+物件」的組合 模組塊化程式設計思想:就是各個板塊/模組 /功能 拼接成一起的東西 ,提出公共的模組。

帶來的好處?

公用&複用性、提供開發效率、方便管理、團隊協作開發 ; 問題:需要自己構建、根據模組間的依賴關係,需要明確匯出順序。 所以就產生了一些其他的模組化規範。

模組化規範 - AMD

AMD 即 Asynchronous Module Definition:非同步模組載入,代表 require.js

RequireJS是一個遵守AMD規範的工具庫,用於客戶端的模組管理。它通過 define 方法,將程式碼定義為模組;通過 require 方法,實現程式碼的模組載入,使用時需要下載和匯入項

 檔案目錄

├── AMD  
    ├── moduleA.js  
    ├── moduleB.js  
    ├── main.js  
    └── require.min.js 

簡單實現一個require.js

let factories = {}
function define(moduleName,factory) {
  factories[moduleName] = factory
}
function require(modules,callback) {
  modules = modules.map(function(item){
    let factory = factories[item];  // 定義好每一個 然後把它執行
    return factory() // 執行之後返回的東西 放到modules
  });
  callback(...modules) // 然後回掉函式執行這些modules
}
/**使用AMD */
define('moduleA', function() {
  return {
    fn() {
      console.log('moduleA')
    }
  }
  
});
define('moduleB', function() {
  return {
    fn() {
      console.log('moduleB')
    }
  }
  
});
require(['moduleB','moduleA'],function(moduleB,moduleA) {
  moduleB.fn()
  moduleA.fn()
})

模組化規範 - CMD

CMD即 Common Module Definition : 通用模組載入。

CMD(Sea.js )& CommonJs規範(Node.js)。

問題:CommonJs只能在 node 環境下支援,客戶端/瀏覽器不支援  CommonJS 規範

那如何讓瀏覽器支援CommonJs規範? 所以有了 Sea.js  ,也就產生了CMD規範(Sea.js 就是Commonjs規範直接搬到瀏覽器上 )

AMD、CMD 區別

AMD 是 RequireJS 在推廣過程中對模組定義的規範化產出 CMD是SeaJS在推廣過程中對模組化定義的規範化產出

區別:

  • 對於依賴的模組,AMD 是提前執行,CMD 是延遲執行。不過 RequireJS 從 2.0 開始,也改成可以延遲執行(根據寫法不同,處理方式不同)。CMD 推崇 as lazy as possible.
  • CMD 推崇依賴就近,AMD 推崇依賴前置

 ModuleA.js

const sum =  function sum(...args){
  let len = args.length
  let firstItem = args[0]
  if(len === 0) return 0;
  if(len === 1) return firstItem;
  return args.reduce((total,item) => {
    return total + item
  })
}

export default { sum }

moduleB.js

import A from './a.js'
const average = function average(...args) {
  let len = args.length
  let firstItem = args[0]
  if(len === 0) return 0;
  if(len === 1) return firstItem;
  return (A.sum(...args) / args.length).toFixed(2)
}

export default  { average }

main.js

import A from './a.js'
import B from './b.js'
console.log(A.sum(1,2,3))
console.log(B.average(1,2,3))

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script type="module" src="./main.js"></script>
</body>
</html>

注意:

  • es6Module 不需要引入外部依賴,瀏覽器可以直接執行,但要告訴瀏覽器我是esModule規範,type='module'   <script type="module" src="./main.js"></script>
  • es6Module 瀏覽器不支援file協議,要在本地起一個服務,可以在vscode上裝一個live serve外掛,給本地一個服務。

 

模組化規範 - ES6Module

ES6 在語言標準的層面上,實現了模組功能,而且實現得相當簡單,完全可以取代 CommonJS 和 AMD 規範,成為瀏覽器和伺服器通用的模組解決方案

特點:webpack 支援、瀏覽器也支援.        

CommonJS、ES6Module差異

  • CommonJs輸出的是一個值的拷貝,ES6輸出的是值的引用
  • CommonJs是執行時載入,ES Module是編譯時就確認了依賴關係

第二個差異是因為 CommonJS 載入的是一個物件(即module.exports屬性),該物件只有在指令碼執行完才會生成。而 ES6 模組不是物件,它的對外介面只是一種靜態定義,在程式碼靜態解析階段就會生成。

 

 

相關文章