4.10 提取公共代碼
問題一:為什么需要提取公共代碼?
大型網(wǎng)站通常會(huì)由多個(gè)頁(yè)面組成,每個(gè)頁(yè)面都是一個(gè)獨(dú)立的單頁(yè)應(yīng)用。 但由于所有頁(yè)面都采用同樣的技術(shù)棧,以及使用同一套樣式代碼,這導(dǎo)致這些頁(yè)面之間有很多相同的代碼。
如果每個(gè)頁(yè)面的代碼都把這些公共的部分包含進(jìn)去,會(huì)造成以下問題:
相同的資源被重復(fù)的加載,浪費(fèi)用戶的流量和服務(wù)器的成本;
每個(gè)頁(yè)面需要加載的資源太大,導(dǎo)致網(wǎng)頁(yè)首屏加載緩慢,影響用戶體驗(yàn)。
如果把多個(gè)頁(yè)面公共的代碼抽離成單獨(dú)的文件,就能優(yōu)化以上問題。 原因是假如用戶訪問了網(wǎng)站的其中一個(gè)網(wǎng)頁(yè),那么訪問這個(gè)網(wǎng)站下的其它網(wǎng)頁(yè)的概率將非常大。 在用戶第一次訪問后,這些頁(yè)面公共代碼的文件已經(jīng)被瀏覽器緩存起來,在用戶切換到其它頁(yè)面時(shí),存放公共代碼的文件就不會(huì)再重新加載,而是直接從緩存中獲取。 這樣做后有如下好處:
減少網(wǎng)絡(luò)傳輸流量,降低服務(wù)器成本;
雖然用戶第一次打開網(wǎng)站的速度得不到優(yōu)化,但之后訪問其它頁(yè)面的速度將大大提升。
問題二:如何提取公共代碼?
根據(jù)你網(wǎng)站所使用的技術(shù)棧,找出網(wǎng)站所有頁(yè)面都需要用到的基礎(chǔ)庫(kù),以采用 React 技術(shù)棧的網(wǎng)站為例,所有頁(yè)面都會(huì)依賴 react、react-dom 等庫(kù),把它們提取到一個(gè)單獨(dú)的文件。 一般把這個(gè)文件叫做base.js,因?yàn)樗芯W(wǎng)頁(yè)的基礎(chǔ)運(yùn)行環(huán)境;
在剔除了各個(gè)頁(yè)面中被base.js包含的部分代碼外,再找出所有頁(yè)面都依賴的公共部分的代碼提取出來放到common.js中去。
再為每個(gè)網(wǎng)頁(yè)都生成一個(gè)單獨(dú)的文件,這個(gè)文件中不再包含base.js和common.js中包含的部分,而只包含各個(gè)頁(yè)面單獨(dú)需要的部分代碼。
問題三:既然能找出所有頁(yè)面都依賴的公共代碼,并提取出來放到common.js中去,為什么還需要再把網(wǎng)站所有頁(yè)面都需要用到的基礎(chǔ)庫(kù)提取到base.js去呢?
原因是為了長(zhǎng)期的緩存base.js這個(gè)文件。
發(fā)布到線上的文件都會(huì)采用在CDN加速的方法,對(duì)靜態(tài)文件的文件名都附加根據(jù)文件內(nèi)容計(jì)算出 Hash 值,也就是最終base.js的文件名會(huì)變成base_3b1682ac.js,以長(zhǎng)期緩存文件。 網(wǎng)站通常會(huì)不斷的更新發(fā)布,每次發(fā)布都會(huì)導(dǎo)致common.js和各個(gè)網(wǎng)頁(yè)的 JavaScript 文件都會(huì)因?yàn)槲募?nèi)容發(fā)生變化而導(dǎo)致其 Hash 值被更新,也就是緩存被更新。
把所有頁(yè)面都需要用到的基礎(chǔ)庫(kù)提取到base.js的好處在于只要不升級(jí)基礎(chǔ)庫(kù)的版本,base.js的文件內(nèi)容就不會(huì)變化,Hash 值不會(huì)被更新,緩存就不會(huì)被更新。 每次發(fā)布瀏覽器都會(huì)使用被緩存的base.js文件,而不用去重新下載base.js文件。 由于base.js通常會(huì)很大,這對(duì)提升網(wǎng)頁(yè)加速速度能起到很大的效果。