一個微信面試題引發(fā)的血案--[譯]什么阻塞了DOM茴她?

譯者注:昨天一篇工作僅一年的前端工程師面試幾個大廠的文章 引起了很多人的關注寻拂。一方面大家覺得作者太厲害了,工作近一年丈牢,能力竟然這么強(大叔我表示慚愧)祭钉,另一方面幾個微信面試題引起很多討論。其中我比較感興趣的一個題目是關于JavaScript和CSS阻塞DOM的己沛。老實話講慌核,我以前也沒太關注過,與其哀嘆自己研究的不夠深入申尼,不如我們?nèi)W習彌補一下吧垮卓。這篇文章是我今天讀到的,感覺不錯师幕,翻譯一下給大家共享粟按。

原文地址:https://www.keycdn.com/blog/blocking-the-dom/
原文作者:BRIAN JACKSON
譯者:接灰的電子產(chǎn)品


當我們談到web性能或者優(yōu)化頁面級別的速度時,非常重要的一點是要理解HTML和一個頁面是如何在瀏覽器中構(gòu)造的霹粥,這樣你才能找到由于渲染阻塞導致的頁面加載延遲灭将。在這篇文章中,我們會深入了解是 什么阻塞了DOM 以及你應該怎樣避免這種情況后控。

什么是DOM庙曙?

DOM是Document Object Model(文檔對象模型)的縮寫。它是為HTML和XML定義的一個編程接口浩淘,提供了文檔的結(jié)構(gòu)化表示(節(jié)點樹狀結(jié)構(gòu))捌朴,同時也規(guī)定了使用腳本編程語言(例如JavaScript)應該如何訪問以及操作DOM。這樣一個節(jié)點樹狀結(jié)構(gòu)是由不同的元素张抄、父節(jié)點砂蔽、子節(jié)點、兄弟節(jié)點等構(gòu)成署惯,它們彼此都有層級化的關系察皇。下圖是一個HTML DOM的例子:

HTML DOM
HTML DOM

用人話描述DOM

簡單的講,當你使用一個類似Chrome開發(fā)者工具的東東時,你可以看到一個可視化的DOM什荣。你的HTML并不是DOM矾缓,但Chrome開發(fā)者工具為你展現(xiàn)了一個經(jīng)過HTML或JavaScript加工之后的DOM。所以你可以把DOM理解成解析后的HTML稻爬。

Chrome開發(fā)者工具中體現(xiàn)的DOM
Chrome開發(fā)者工具中體現(xiàn)的DOM

什么在阻塞DOM嗜闻?

當我們分析頁面速度時,我們總要考慮什么阻塞了DOM導致我們的頁面加載出現(xiàn)延遲桅锄。這些阻塞因素我們可以叫做 阻塞渲染的資源 琉雳,例如 HTML、CSS(也包括web font)和 JavaScript友瘤。

要查看什么阻塞了DOM的最簡單的方法之一就是使用 Chrome開發(fā)者工具 (Chrome DevTools) 和Google的 PageSpeed Insight翠肘。在下面的例子中,我們使用了最新的Chrome開發(fā)者工具 (可以通過 Chrome Canary 獲得)辫秧。

  1. 在Chrome中啟動開發(fā)者工具
  • Windows:F12 或者 Ctrl + Shift + I
  • Mac: Cmd + Opt + I
  1. 切換到 Network (網(wǎng)絡)面板束倍,刷新頁面( Win: Ctrl + R, Mac: Cmd + R
  2. 現(xiàn)在你會看到一個加載時間瀑布圖。這里有兩個值得我們關注的東東:第一個是 DOMContentLoaded 是384ms(譯者注:原文如此盟戏,看圖的話應該是281ms)绪妹,第二個就是瀑布圖中的在藍線之前的綠色部分(譯者注:原圖有點問題,藍線看起來是紫色的)

我們知道CSS和JavaScript都是阻塞渲染的資源柿究,它們都會在藍色的DOMContent之前加載邮旷。請注意,圖像是不會阻塞渲染的 蝇摸,所以如果有圖像落在藍線之前或之上你可以放心的忽略掉婶肩,當然優(yōu)化圖像也是很重要的一項工作。在這個例子里面貌夕,我們可以看到 style.cssjquery.min.js 都是阻塞渲染的資源律歼。

Chrome開發(fā)者工具的網(wǎng)絡面板中的加載時間瀑布圖
Chrome開發(fā)者工具的網(wǎng)絡面板中的加載時間瀑布圖

你同樣可以通過 Google PageSpeed Insightshttps://developers.google.com/speed/pagespeed/insights/) 工具來驗證我們上面的結(jié)論。下圖中顯示這兩個文件的確是阻塞渲染的蜂嗽。

Google PageSpeed Insights
Google PageSpeed Insights

我們下面要學習的是如何 通過優(yōu)化關鍵渲染路徑來避免CSS和JavaScript阻塞DOM 。盡管HTML也算是一個阻塞渲染的資源(譯者注:記住HTML不是DOM)殃恒,但DOM是可以增量構(gòu)建的(譯者注:所以優(yōu)化的是CSS和JavaScript植旧,而不是HTML)。

注意离唐,我們無需追求在 Google PageSpeed Insights100/100病附。例如,如果你鏈接引用了Google的web字體亥鬓,那么無論你做什么完沪,這個外部的 fonts.googleapis.com 樣式都始終會是一個阻塞渲染的資源。重要的是當你在處理有著10+個阻塞渲染資源的一個大型站點時,要理解清楚什么導致了延遲覆积,有什么樣的策略可以使這些資源可以更有效率的加載听皿。

CSS

非渲染阻塞的CSS

如果你追求一個完全沒有阻塞的CSS,那么你的唯一選項就是:在HTML中內(nèi)聯(lián)嵌入你的CSS宽档。你可以把需要初始渲染的CSS尉姨,一般來講就是第一屏的樣式,直接放在 HEAD 里面的 <style></style> 中吗冤,然后剩下的CSS放在 </body> 之前又厉。這樣做可以完全避免CSS阻塞渲染。

有幾個可以輔助你完成內(nèi)聯(lián)樣式嵌入的自動化插件

你當然也可以使用JavaScript來加載CSS椎瘟,但是這樣做會導致頁面在加載結(jié)束時重繪覆致,因此這個選項對于網(wǎng)站訪問者來說不一定會很理想。

在Chrome開發(fā)者工具中可以看到肺蔚,我們做完內(nèi)聯(lián)樣式優(yōu)化之后的版本中 DOMContentLoaded 減少到了 278ms

內(nèi)聯(lián)優(yōu)化后的版本
內(nèi)聯(lián)優(yōu)化后的版本

現(xiàn)在我們再去 Google PageSpeed Insights 測試煌妈,會發(fā)現(xiàn)CSS已不是阻塞渲染的資源了。

內(nèi)聯(lián)優(yōu)化后的測試
內(nèi)聯(lián)優(yōu)化后的測試

當然這很不錯婆排,但一切取決于你的站點實際情況声旺。大多數(shù)站點并不想內(nèi)聯(lián)嵌入所有的CSS,因為CSS的內(nèi)容多少直接且顯著的影響了頁面下載的大小段只。對于小型站點或者就是個 Landing Page 腮猖,這種情況下內(nèi)聯(lián)嵌入CSS可以是一個不錯的選項,如果你真的想完全避免CSS阻塞渲染的話赞枕。

我們的CSS建議

即使在我們自己的KeyCDN主頁上澈缺,我們也有一個阻塞渲染的CSS。但是炕婶,我們做了其他一些事情來優(yōu)化CSS的加載時間姐赡,下面是我們的建議:

  1. 正確的調(diào)用你的CSS文件 (譯者注:原文如此,感覺應該是位置或時機柠掂?)
  2. 使用 media queries (媒體查詢) 來標記某些CSS為非阻塞資源 (譯者注: 比如 <link href="other.css" rel="stylesheet" media="(min-width: 40em)"> 這樣可以在其他屏幕尺寸加載時就不用加載這個css了)
  3. 減少CSS的數(shù)量(盡可能放到一個CSS文件中)
  4. Minify CSS文件(刪除多余的空格项滑、字符、注釋等)
  5. 盡可能的減少樣式數(shù)量(譯者注:和第三條不同涯贞,是減少樣式數(shù)量枪狂,不是文件數(shù)量)

一些用于最小化(Minify)CSS的工具

JavaScript

非渲染阻塞的JavaScript

有一些關于JavaScript的最佳實踐需要牢記在心:

  1. 把腳本放在頁面尾部 </body> 之前的位置
  2. 使用async或defer指令來避免阻塞渲染

異步加載JavaScript

async 允許腳本在后臺下載,因此是無阻塞的宋渔。但是當下載完成的時刻州疾,渲染又會阻塞了,這是因為腳本執(zhí)行了皇拣。當腳本執(zhí)行完畢严蓖,渲染又恢復了。

<script async src="foobar.js"></script>

延遲加載JavaScript

defer 指令做的事情和 async 基本一樣,區(qū)別點在于 defer 是嚴格要求腳本的執(zhí)行順序必須和在HTML中標記的順序一樣颗胡。所以說毫深,可能存在一種情況,當一些腳本已經(jīng)下載完畢杭措,這些腳本不會立即執(zhí)行费什,它們會等待其他腳本下載完成,因為那些腳本在HTML中出現(xiàn)在它們之前手素。

Patrick Sexton寫了一篇非常好的博文: 如何延遲加載JavaScript

除去上面兩條鸳址,我們對于JavaScript的另外3條建議是:

  1. 減少JavaScript的數(shù)量(盡量整合成一個JS文件)
  2. Minify(最小化)JavaScript
  3. 如果JavaScript很小的話,可以內(nèi)聯(lián)嵌入

用于最小化JavaScript的自動化任務插件

通過把我們的JavaScript移動到頁面尾部泉懦,以及使用 async 指令之后稿黍,我們把 DOMContentLoaded 顯著的減少到了 144ms。我們可以看到 jquery.min.js 文件現(xiàn)在出現(xiàn)在了DOM的藍線之后了崩哩。

JavaScript優(yōu)化后在Chrome開發(fā)者工具中的表現(xiàn)
JavaScript優(yōu)化后在Chrome開發(fā)者工具中的表現(xiàn)

那么在 Google PageSpeed Insights 中同樣的巡球,由于我們已經(jīng)異步加載了JavaScript,所以這一項的扣分不存在了邓嘹,我們達成了 100/100 酣栈。

達成100分
達成100分

Web Fonts

Web Fonts(Web字體)也被視為一種阻塞渲染的資源,因為它們是通過CSS加載的。你有兩個選擇:阻塞渲染或者延遲重繪(這種情況你需要處理 FOUT)。舉個例子锌唾,在Chrome(36以上版本)崇败,Opera(23以上版本)和Firefox中有一個 three-second timeout真慢,在超時后,fall-back字體會被使用。

同樣的我們有幾個關于加載字體和優(yōu)化關鍵渲染路徑的小建議:

  1. 使用Web Font加載器或者字體加載API
  2. 使用內(nèi)聯(lián)嵌入優(yōu)化字體加載
  3. 使用例如localStorage等存儲方法

關于更多深入的加載Web Fonts、如何避免渲染阻塞以及FOUT/FOIT等可以查看這篇博文:
analyzing web font performance

小總結(jié)

我們希望到這里你可以對阻塞DOM铸史、DOM樹是如何構(gòu)建的,為何會被CSS和JavaScript阻塞等問題有了一些了解怯伊。請再次記住不要追求 Google PageSpeed Insights100/100琳轿,重要的是理解你的渲染阻塞資源是如何阻塞DOM的以及你會怎樣正確的優(yōu)化使得頁面的加載變快。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末耿芹,一起剝皮案震驚了整個濱河市崭篡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌猩系,老刑警劉巖媚送,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件中燥,死亡現(xiàn)場離奇詭異寇甸,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進店門拿霉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吟秩,“玉大人,你說我怎么就攤上這事绽淘『溃” “怎么了?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵沪铭,是天一觀的道長壮池。 經(jīng)常有香客問我,道長杀怠,這世上最難降的妖魔是什么椰憋? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮赔退,結(jié)果婚禮上橙依,老公的妹妹穿的比我還像新娘。我一直安慰自己硕旗,他們只是感情好窗骑,可當我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著漆枚,像睡著了一般创译。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上浪读,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天昔榴,我揣著相機與錄音,去河邊找鬼碘橘。 笑死互订,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的痘拆。 我是一名探鬼主播仰禽,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼纺蛆!你這毒婦竟也來了吐葵?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤桥氏,失蹤者是張志新(化名)和其女友劉穎温峭,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體字支,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡凤藏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年奸忽,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片揖庄。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡栗菜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蹄梢,到底是詐尸還是另有隱情疙筹,我是刑警寧澤,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布禁炒,位于F島的核電站而咆,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏幕袱。R本人自食惡果不足惜翘盖,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望凹蜂。 院中可真熱鬧馍驯,春花似錦、人聲如沸玛痊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽擂煞。三九已至混弥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間对省,已是汗流浹背蝗拿。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蒿涎,地道東北人哀托。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像劳秋,于是被迫代替她去往敵國和親仓手。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容