前端系統(tǒng)學習 2. 模塊化

1. 無模塊化

實現(xiàn):文件分離,順序導入

缺點:污染全局作用域,變量名沖突導致的報錯

2. IIFE (Immediately-invoked Function Expression)

實現(xiàn):利用函數(shù)塊級作用域

const iifeModule = (function(){

  let count = 1
  function increase () {
    return ++count
  }
  function reset () {
    return count = 0
  }
  return {
    increase,
    reset
  }

})()

iifeModule.increase()
iifeModule.reset()

優(yōu)化IIFE,加入模塊依賴

模塊導入使用 iife 傳參,模塊導出使用 iife 的返回值

const iifeModule = (function(dependency1, dependency2){
  let count = 1
  function increase () {
    return ++count
  }
  function reset () {
    return count = 0
  }
  return {
    increase,
    reset
  }
})(dependency1, dependency2)

iifeModule.increase()
iifeModule.reset()

Revealing Module Pattern

揭示模式模仿了 OOP 的思想,隱藏私有變量,只暴露公有變量和函數(shù)來操作私有變量

IIFE 優(yōu)點:

  • 從語法側解決了全局變量作用域的問題,有了模塊的雛形

IIFE 缺點:

  • 多余的語法代碼
  • 除了解決作用域的問題,其他的復雜場景問題一概沒有考慮

3. CJS - Commonjs

nodejs 的模塊化方案

每個文件就是一個模塊,有自己的作用域。在一個文件里面定義的變量、函數(shù)、類,都是私有的,對其他文件不可見。

CJS 規(guī)范

CommonJS規(guī)范規(guī)定,每個模塊內(nèi)部,module變量代表當前模塊。這個變量是一個對象,它的exports屬性(即module.exports)是對外的接口。加載某個模塊,其實是加載該模塊的module.exports屬性。
require方法用于加載模塊

const dep1 = require('dep1Module')
const dep2 = require('dep2Module')

// use object dep1 do sth
...

exports.a = a
exports.b = b

// Or
module.exports = {
  a, b
}

實現(xiàn)邏輯

使用

(function (require, module, exports) {
  // use require
  require(...)

  // use exports
  exports.a = a

  // use module.exports
  module.exports = {
    a
  }

})()

// require 模擬
function require(dep) {
  // 定義閉包bm'ld
  const module = {}
  module.exports = {}

  const code = file.readFileSync('dep')

  // 函數(shù)執(zhí)行完成之后,module.exports 將會被賦值
  new Function('require', 'module', 'exports', code)(require, module, exports)

  // 導出 dep 的 emodule.exports
  return module.exports
}
  • 優(yōu)點
    CommonJS 率先在服務端實現(xiàn)了,從框架層面解決全局變量污染依賴的問題
  • 缺點
    主要是服務端的解決方案,不適用于客戶端異步拉取依賴的場景

拋出新的問題 —— 異步依賴

4. AMD (Asynchronous Module Definition)

通過異步加載 + 允許定制回調

經(jīng)典實現(xiàn)框架:require.js

定義方式

/**
* 通過 define 定義一個模塊,然后通過 require 進行加載
* 最后一個參數(shù)是 工廠方法
**/
define(id, [...deps], callback)
require([...module], callback)

模塊的定義

define('myModule', ['dep1', 'dep2'], (dep1, dep2) => {
  // 業(yè)務邏輯
  let count = 0;
  const increase = () => ++count;
  const reset = () => {
    count = 0;
  }

  return {
    increase, reset
  }
})

模塊的引入

require(['myModule'], myModule => {
  myModule.increase()
})
  • 優(yōu)點:解決了瀏覽器異步加載依賴場景的問題,可以并行加載多個模塊
  • 缺點:不能按需加載

5. UMD (Universal Module Definition)

UMD 頂部一般有這樣一段代碼來兼容 CJS 和 AMD

(function(root, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD
    define(['jquery', factory])
  } else if (typeof 'exports' === 'object') {
    // CJS
    module.exports = factory(require('jquery'))
  } else {
    // 將模塊綁定在全局變量上
    // 這里的 root.jQuery 也是之前已經(jīng)綁定了的 module
    root.myModule = factory(root.jQuery)
  }
})(this, function ($) {
  // myModule 業(yè)務代碼
  return {
    a,
    b
  }
})
  • 優(yōu)點:兼容 AMD 和 CJS,可以在雙端運行
  • 缺點:未解決 AMD 無法按需加載的問題

6. CMD (Common Module Definition)

規(guī)范draft

主要應用框架 sea.js

require & require.async

  • require 導入同步模塊
  • require.async 導入異步模塊,第二個參數(shù)是 callback
define('myModule', (require, exports, module) => {
  let $ = require('jquery')
  // jquery 相關邏輯
  ...

  let dep1 = require.async(['dep1'], dep1 => {
    // dep1 module 相關業(yè)務邏輯
    ...

  })

})
  • 優(yōu)點:按需加載,同時支持同步和異步 require
  • 缺點:依賴打包,加載邏輯存在于每個模塊中,模塊體積擴大

ESM

使用

import 導入模塊
export 導出模塊,export default 導出默認模塊

import dep1 from 'dep1'

// 業(yè)務邏輯
let count = 0
export const increase = () => ++count
export const reset = () => count = 0

export default {
  increase, reset
}

模板引入

<script type="module" src="myModule.js"></script>

node 端引入,mjs

import { increase, reset } from './myModule.mjs'

increase()
reset()

動態(tài)導入

ES11 原生解決方案

import('dep').then(dep => {
  ...
})
  • 優(yōu)點:官方提出的統(tǒng)一形態(tài)的模塊化,解決了上面遇到的各種問題
    (模塊作用域、依賴導入導出、異步導入等)
  • 缺點:本質上還是運行時的依賴分析

解決模塊化的新思路 —— 前端工程化

背景

根本問題 —— 運行時的依賴分析

方案:編譯時分析依賴,同時優(yōu)化項目
grunt gulp webpack vite

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容