1. 無模塊化
實(shí)現(xiàn):文件分離俺泣,順序?qū)?/p>
缺點(diǎn):污染全局作用域罗侯,變量名沖突導(dǎo)致的報(bào)錯(cuò)
2. IIFE (Immediately-invoked Function Expression)
實(shí)現(xiàn):利用函數(shù)塊級(jí)作用域
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,加入模塊依賴
模塊導(dǎo)入使用 iife 傳參月杉,模塊導(dǎo)出使用 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)點(diǎn):
- 從語法側(cè)解決了全局變量作用域的問題苛萎,有了模塊的雛形
IIFE 缺點(diǎn):
- 多余的語法代碼
- 除了解決作用域的問題桨昙,其他的復(fù)雜場(chǎng)景問題一概沒有考慮
3. CJS - Commonjs
nodejs 的模塊化方案
每個(gè)文件就是一個(gè)模塊,有自己的作用域首懈。在一個(gè)文件里面定義的變量绊率、函數(shù)谨敛、類究履,都是私有的,對(duì)其他文件不可見脸狸。
CommonJS規(guī)范規(guī)定最仑,每個(gè)模塊內(nèi)部,module變量代表當(dāng)前模塊炊甲。這個(gè)變量是一個(gè)對(duì)象泥彤,它的exports屬性(即module.exports)是對(duì)外的接口。加載某個(gè)模塊卿啡,其實(shí)是加載該模塊的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
}
實(shí)現(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 將會(huì)被賦值
new Function('require', 'module', 'exports', code)(require, module, exports)
// 導(dǎo)出 dep 的 emodule.exports
return module.exports
}
-
優(yōu)點(diǎn):
CommonJS 率先在服務(wù)端實(shí)現(xiàn)了颈娜,從框架層面解決全局變量污染
剑逃、依賴
的問題 -
缺點(diǎn):
主要是服務(wù)端的解決方案,不適用于客戶端異步拉取依賴的場(chǎng)景
拋出新的問題 —— 異步依賴
4. AMD (Asynchronous Module Definition)
通過異步加載 + 允許定制回調(diào)
經(jīng)典實(shí)現(xiàn)框架:require.js
定義方式
/**
* 通過 define 定義一個(gè)模塊官辽,然后通過 require 進(jìn)行加載
* 最后一個(gè)參數(shù)是 工廠方法
**/
define(id, [...deps], callback)
require([...module], callback)
模塊的定義
define('myModule', ['dep1', 'dep2'], (dep1, dep2) => {
// 業(yè)務(wù)邏輯
let count = 0;
const increase = () => ++count;
const reset = () => {
count = 0;
}
return {
increase, reset
}
})
模塊的引入
require(['myModule'], myModule => {
myModule.increase()
})
- 優(yōu)點(diǎn):解決了瀏覽器異步加載依賴場(chǎng)景的問題蛹磺,可以并行加載多個(gè)模塊
- 缺點(diǎn):不能按需加載
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è)務(wù)代碼
return {
a,
b
}
})
- 優(yōu)點(diǎn):兼容 AMD 和 CJS,可以在雙端運(yùn)行
- 缺點(diǎn):未解決 AMD 無法按需加載的問題
6. CMD (Common Module Definition)
主要應(yīng)用框架 sea.js
require & require.async
- require 導(dǎo)入同步模塊
- require.async 導(dǎo)入異步模塊同仆,第二個(gè)參數(shù)是 callback
define('myModule', (require, exports, module) => {
let $ = require('jquery')
// jquery 相關(guān)邏輯
...
let dep1 = require.async(['dep1'], dep1 => {
// dep1 module 相關(guān)業(yè)務(wù)邏輯
...
})
})
- 優(yōu)點(diǎn):按需加載萤捆,同時(shí)支持同步和異步 require
- 缺點(diǎn):依賴打包,加載邏輯存在于每個(gè)模塊中,模塊體積擴(kuò)大
ESM
使用
import 導(dǎo)入模塊
export 導(dǎo)出模塊俗或,export default 導(dǎo)出默認(rèn)模塊
import dep1 from 'dep1'
// 業(yè)務(wù)邏輯
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()
動(dòng)態(tài)導(dǎo)入
ES11 原生解決方案
import('dep').then(dep => {
...
})
- 優(yōu)點(diǎn):官方提出的統(tǒng)一形態(tài)的模塊化,解決了上面遇到的各種問題
(模塊作用域辛慰、依賴導(dǎo)入導(dǎo)出焰轻、異步導(dǎo)入等) - 缺點(diǎn):本質(zhì)上還是運(yùn)行時(shí)的依賴分析
解決模塊化的新思路 —— 前端工程化
背景
根本問題 —— 運(yùn)行時(shí)的依賴分析
方案:編譯時(shí)分析依賴,同時(shí)優(yōu)化項(xiàng)目
grunt gulp webpack vite