2020 前端模塊化

在了解模塊化的概念前,首先先解決一個問題 - 為什么需要模塊化杈曲?

先從實際問題出發(fā)例朱,在類似require.js孝情、sea.js、browserify洒嗤、webpack等工具出現(xiàn)之前箫荡,我們可能會遇到如下一些問題:

我們在引用不同的庫或者js文件時,可能會出現(xiàn)命名沖突渔隶。

引用的庫或者文件都會有個先來后到羔挡,那如何去決定與維護這些順序呢?

庫與庫之間间唉、文件與文件之間可能存在循環(huán)引用绞灼,即在a.js中引用了b.js,而b.js中也引用了a.js呈野;兩者相互依賴低矮。那我們?nèi)绾螞Q定先引用哪個件呢?

我們再從一個生活中的例子出發(fā)被冒,簡要了解一下模塊化的優(yōu)點军掂,即為什么需要模塊化的原因。

假設(shè)你有一套修理工具箱昨悼,里面包含了屬于這套修理工具箱的各種型號的螺絲批蝗锥、鉗子和錘子等等。每次家里水管破了率触,燈泡壞了什么的终议,你都可以拿這套修理工具箱進行修理。每次修理可能都會造成一些工具的損耗或損壞葱蝗,損壞之后我們就應(yīng)該去買相同型號的工具進行補充穴张;其他不對頭的工具不會回收回這套修理工具箱中,同樣這套修理工具箱中的工具也不會隨意扔出工具箱中两曼。

我們把上述例子轉(zhuǎn)化為模塊化來看看皂甘。首先,修理工具箱就是模塊合愈,里面的工具就是模塊中的各種變量或函數(shù)叮贩。工具出現(xiàn)損壞等于模塊內(nèi)出了什么問題击狮,這時候我們只需要修復(fù)模塊內(nèi)的bug就好了佛析。其他不對頭的工具不會回收回工具箱中,反之工具箱中的工具不會隨意被扔出表示模塊內(nèi)的變量彪蓬、函數(shù)等不會污染外部的變量寸莫、函數(shù)等等,反之亦然档冬。這套工具箱可以重復(fù)利用也就是模塊的復(fù)用性很強膘茎。

總結(jié)模塊化有三大優(yōu)點:

可維護性強桃纯,更新或修復(fù)模塊內(nèi)的邏輯不會影響外部邏輯

獨立的命名空間,模塊內(nèi)的變量不會污染外部的變量披坏,即使它們擁有相同的變量名

可復(fù)用性強态坦,我們需要在不同的地方用到某個模塊,只需要在對應(yīng)的地方引入它就行了棒拂,無需重復(fù)地拷貝復(fù)制伞梯。



什么是模塊化


var module = (function () {

? var _privateCnt = 0

? var _privateProperty = 'I am private property'

? function _privateCnter () {

? ? return _privateCnt += 1

? }

? function publicCnter () {

? ? return _privateCnter()

? }

? return {

? ? property: _privateProperty,

? ? publicCnter: publicCnter

? }

})()

console.log(module.property) // I am private property

console.log(module.publicCnter()) // 1

console.log(module.publicCnter()) // 2

console.log(module.publicCnter()) // 3

這個例子展示了通過立即執(zhí)行函數(shù)表達式將一些變量、方法暴露出去帚屉,并防止外部直接修改一些我們不希望修改的變量谜诫、方法。這樣做還有一個好處攻旦,就是我們可以快速地了解到這個立即執(zhí)行函數(shù)為我們提供了哪些公共屬性及方法喻旷,而不需要閱讀所有邏輯代碼。這種方式在設(shè)計模式中也稱作模塊模式(Module Pattern)牢屋。



CommonJS

CommonJS主要是為服務(wù)端定義的模塊規(guī)范且预,它一開始的名字為ServerJS。npm生態(tài)系統(tǒng)基本都是基于CommonJS規(guī)范所建立起來的伟阔。

// 在 foo.js 中辣之,我們導(dǎo)出了變量 foomodule.exports = {foo:'foo'}// 在 bar.js,我們通過 require 引入了變量 foovarmodule=require('foo')console.log(module.foo)// foo復(fù)制代碼

看起來很簡單是吧皱炉』彻溃可能有人會問了,這個module是什么東西呢合搅?其實module是 Node 中的一個內(nèi)置對象多搀。我們可以在node環(huán)境下打印看看


們可以看到?module?有好幾個屬性,其中?id?是為了讓?node?知道這個模塊在哪里灾部,是啥康铭;exports?就是我們要導(dǎo)出的對象了。在確保?foo.js?和?bar.js?在同一目錄下赌髓,我們再將例子稍加修改:


// foo,js

module.exports = {

? foo: 'foo'

}

console.log('module: ', module)

// bar.js

var module = require('./foo')

console.log(module.foo)


通過 CommonJS 規(guī)范定義的模塊同樣有一開始說到的模塊的三大優(yōu)點从藤,其實我們只需要把這些模塊文件看出一個個立即執(zhí)行函數(shù),也就會很好理解了锁蠕。 在 CommonJS 里模塊都是同步加載的夷野,在瀏覽器中如果同步去加載模塊的話會造成阻塞,導(dǎo)致頁面性能下降荣倾;而在服務(wù)端中悯搔,因為文件都存在于同一個硬盤上,所以即使是同步加載都不會有什么影響舌仍。 再補充一個小細節(jié)妒貌,你可能時不時能看到 var exports = module.exports 這樣的代碼通危。或許你會問為什么要怎么做灌曙,難道有什么技巧嗎菊碟?其實這只是簡單的引用而已。即變量 exports 同樣指向了 module.exports 的內(nèi)存地址在刺,也就是兩者指向的對象是完全一樣的框沟。我們想在 module.exports 里添加導(dǎo)出的東西時,只需要在 exports 里加就行了增炭。就是這么簡單忍燥,只不過被一些說法搞得高深莫測了而已。




ES Modules

CommonJS在服務(wù)端中應(yīng)用廣泛隙姿,但由于它是同步加載模塊的梅垄,它在客戶端不太合適;而AMD支持瀏覽器異步加載模塊输玷,但在服務(wù)端卻顯得沒有必要队丝,因此ES Modules出現(xiàn)了。我們先來看看ES Modules是如何工作的欲鹏。

ES Modules與CommonJS很相似机久,較新的瀏覽器均已支持ES Modules,Node.js正在慢慢支持相關(guān)規(guī)范赔嚎。

ES Modules的核心為export與import膘盖,分別對應(yīng)導(dǎo)出模塊與導(dǎo)入模塊。

導(dǎo)出模塊:

// CommonJS

module.exports = foo () {

? console.log('here is foo')

}

// ES Modules

export default function bar () {

? console.log('here is bar')

}

// CommonJS

var foo = require('./foo')

foo() // here is foo

// ES Modules

import bar from './bar'

bar() // here is bar

這兩者這么相似尤误,它們在實際的表現(xiàn)上有什么不同呢侠畔?

我分別在Firefox、Edge和Chrome上測試(Chrome由于自身的安全策略無法直接通過本地文件進行測試损晤,所以利用插件Web Server for Chrome起了個本地服務(wù)器软棺。

測試代碼如下圖(注意我們在使用ES Modules時要給script標簽加上type="module")


? 我們來看看打印結(jié)果

? ? ?開始執(zhí)行 bar.js

? ? ? ? ? ? ? ? ? 開始執(zhí)行 foo.js

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?here is foo

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?here is bar



很顯然CommonJS是同步加載模塊的,所以代碼的執(zhí)行也是順序的尤勋。而ES Modules是異步加載模塊的喘落,且ES Modules是編譯時加載模塊,在運行時(執(zhí)行代碼時)再根據(jù)相關(guān)的引用去被加載的模塊中取值最冰。再詳細一點來說的話瘦棋,整個過程分如下三個步驟:

構(gòu)建 - 查找、下載并將文件解析到模塊記錄中

實例化 - 在內(nèi)存中找到所有導(dǎo)出(export)的值的位置锌奴,但暫不對這些值進行賦值兽狭;然后在內(nèi)存中創(chuàng)建exports和imports的空間憾股。這一步稱為鏈接

運行 - 運行代碼并將實際的值賦予給實例化中導(dǎo)出的值


因此在編譯期間鹿蜀,編譯器先找到了foo.js的依賴bar.js箕慧,先編譯bar.js然后才是foo.js。所以你才會先看到開始執(zhí)行 bar.js茴恰。

總結(jié)

模塊化簡單來說就是將相關(guān)的邏輯代碼獨立出來颠焦,獨立的形式有很多種,可以是單純的一個函數(shù)往枣,亦可以是單獨的一個文件伐庭。

模塊化可以更好地組織代碼結(jié)構(gòu),增強其可維護性分冈,可復(fù)用性強圾另。

CommonJS工作原理為同步加載模塊,在Node.js中有著廣泛的使用雕沉,對客戶端不友好集乔。

AMD工作原理為異步加載模塊。

ES Modules為ES6推出的規(guī)范坡椒,客戶端的支持比較好扰路,Node.js將會慢慢全面支持。它與AMD一樣倔叼,也是異步加載模塊汗唱。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市丈攒,隨后出現(xiàn)的幾起案子哩罪,更是在濱河造成了極大的恐慌,老刑警劉巖巡验,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件识椰,死亡現(xiàn)場離奇詭異,居然都是意外死亡深碱,警方通過查閱死者的電腦和手機腹鹉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來敷硅,“玉大人功咒,你說我怎么就攤上這事〗时模” “怎么了力奋?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長幽七。 經(jīng)常有香客問我景殷,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任猿挚,我火速辦了婚禮咐旧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘绩蜻。我一直安慰自己铣墨,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布办绝。 她就那樣靜靜地躺著伊约,像睡著了一般。 火紅的嫁衣襯著肌膚如雪孕蝉。 梳的紋絲不亂的頭發(fā)上屡律,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天,我揣著相機與錄音降淮,去河邊找鬼疹尾。 笑死,一個胖子當(dāng)著我的面吹牛骤肛,可吹牛的內(nèi)容都是我干的纳本。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼腋颠,長吁一口氣:“原來是場噩夢啊……” “哼繁成!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起淑玫,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤巾腕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后絮蒿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體尊搬,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年土涝,在試婚紗的時候發(fā)現(xiàn)自己被綠了佛寿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡但壮,死狀恐怖冀泻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蜡饵,我是刑警寧澤弹渔,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站溯祸,受9級特大地震影響肢专,放射性物質(zhì)發(fā)生泄漏舞肆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一博杖、第九天 我趴在偏房一處隱蔽的房頂上張望椿胯。 院中可真熱鬧,春花似錦欧募、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至镣丑,卻和暖如春舔糖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背莺匠。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工金吗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人趣竣。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓摇庙,卻偏偏與公主長得像,于是被迫代替她去往敵國和親遥缕。 傳聞我的和親對象是個殘疾皇子卫袒,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,515評論 2 359