日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

JS一定要放在Body的最底部么?

發(fā)布時(shí)間:2025/5/22 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JS一定要放在Body的最底部么? 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、從一個(gè)面試題說起

面試前端的時(shí)候我喜歡問一些看上去是常識(shí)的問題。比如:為什么大家普遍把?<script src=""></script>?這樣的代碼放在body最底部??(為了溝通效率,我會(huì)提前和對(duì)方約定所有的討論都以chrome為例)

應(yīng)聘者一般會(huì)回答:因?yàn)闉g覽器生成Dom樹的時(shí)候是一行一行讀HTML代碼的,script標(biāo)簽放在最后面就不會(huì)影響前面的頁面的渲染。

我很雞賊地接著問:既然Dom樹完全生成好后頁面才能渲染出來,瀏覽器又必須讀完全部HTML才能生成完整的Dom樹,script標(biāo)簽不放在body底部是不是也一樣?

留?一?段?空?白?讓?你?先?想?一?想

“頁面渲染出來了” 指的是什么?

嚴(yán)格來說,我的最后一問是有歧義的:我們需要統(tǒng)一一下什么叫我們經(jīng)常掛在嘴邊的“頁面渲染出來了” —— 指的是是 “首屏顯示出來了” 還是 “頁面完整地加載好了”(后面統(tǒng)稱StepC) ?如果指的是首屏顯示出來了,那么問題又來了:假設(shè)網(wǎng)頁首屏有圖片,這里的“首屏” 指的是 “顯示了全部圖片的首屏”(后面統(tǒng)稱StepB) 還是 “沒有圖片的首屏”(后面統(tǒng)稱StepA)。

確定清楚 “頁面渲染出來了” 指的是 StepA、StepB、StepC 中的哪一個(gè)是非常關(guān)鍵的(雖然至今還沒有一個(gè)應(yīng)聘者嘗試這么做過),如果 “頁面渲染出來了” 指的是 StepC,那么我的最后一問的答案是肯定的——script標(biāo)簽不放在body底部不會(huì)拖慢頁面完整地加載好的時(shí)間。

顯然,我們往往更關(guān)心首屏?xí)r間,所以,如果 “頁面渲染出來了” 特指“沒有圖片的首屏”,那我的最后一問變成了下面這樣,又該如何回答呢?

既然Dom樹完全生成好后才能顯示“沒有圖片的首屏”,瀏覽器又必須讀完全部HTML才能生成完整的Dom樹,script標(biāo)簽不放在body底部是不是也一樣?

陷阱

然而上面的問題還是存在一個(gè)陷阱——?既然Dom樹完全生成好后才能顯示“沒有圖片的首屏”?這句話是帶欺騙性的,“沒有圖片的首屏”并不以“完整的Dom樹”為必要條件。也就是說:?在生成Dom樹的過程中只要某些條件具備了,“沒有圖片的首屏”就能顯示出來。

所以,拋開這些歧義和陷阱,我的問題變成了:

script標(biāo)簽的位置會(huì)影響首屏?xí)r間么?

然而答案并不是那么顯而易見,這得從瀏覽器的渲染機(jī)制說起。?(再一次說明:本文所說的瀏覽器都是指chrome)

二、瀏覽器的渲染機(jī)制

首先,我們需要了解幾個(gè)概念:

1、?DOM?:Document Object Model,瀏覽器將HTML解析成樹形的數(shù)據(jù)結(jié)構(gòu),簡(jiǎn)稱DOM。

2、?CSSOM?:CSS Object Model,瀏覽器將CSS代碼解析成樹形的數(shù)據(jù)結(jié)構(gòu)。

3、DOM 和 CSSOM 都是以?Bytes → characters → tokens → nodes → object model.?這樣的方式生成最終的數(shù)據(jù)。如下圖所示:

DOM樹的構(gòu)建過程是一個(gè)深度遍歷過程:當(dāng)前節(jié)點(diǎn)的所有子節(jié)點(diǎn)都構(gòu)建好后才會(huì)去構(gòu)建當(dāng)前節(jié)點(diǎn)的下一個(gè)兄弟節(jié)點(diǎn)。

4、?Render Tree?:DOM 和 CSSOM 合并后生成 Render Tree,如下圖:

Render Tree 和DOM一樣,以多叉樹的形式保存了每個(gè)節(jié)點(diǎn)的css屬性、節(jié)點(diǎn)本身屬性、以及節(jié)點(diǎn)的孩子節(jié)點(diǎn)。

注意:display:none 的節(jié)點(diǎn)不會(huì)被加入Render Tree,而visibility: hidden 則會(huì),所以,如果某個(gè)節(jié)點(diǎn)最開始是不顯示的,設(shè)為display:none是更優(yōu)的。具體可以看?這里

瀏覽器的渲染過程:

1、?Create/Update DOM And request css/image/js?:瀏覽器請(qǐng)求到HTML代碼后,在生成DOM的最開始階段(應(yīng)該是 Bytes → characters 后),并行發(fā)起css、圖片、js的請(qǐng)求,無論他們是否在HEAD里。

注意:發(fā)起js文件的下載request并不需要DOM處理到那個(gè)script節(jié)點(diǎn),比如:簡(jiǎn)單的正則匹配就能做到這一點(diǎn),雖然實(shí)際上并不一定是通過正則:)。這是很多人在理解渲染機(jī)制的時(shí)候存在的誤區(qū)

2、?Create/Update Render CSSOM?:CSS文件下載完成,開始構(gòu)建CSSOM

3、?Create/Update Render Tree?:所有CSS文件下載完成,CSSOM構(gòu)建結(jié)束后,和 DOM 一起生成 Render Tree。

4、?Layout?:有了Render Tree,瀏覽器已經(jīng)能知道網(wǎng)頁中有哪些節(jié)點(diǎn)、各個(gè)節(jié)點(diǎn)的CSS定義以及他們的從屬關(guān)系。下一步操作稱之為?Layout?,顧名思義就是計(jì)算出每個(gè)節(jié)點(diǎn)在屏幕中的位置。

5、?Painting?:Layout后,瀏覽器已經(jīng)知道了哪些節(jié)點(diǎn)要顯示(which nodes are visible)、每個(gè)節(jié)點(diǎn)的CSS屬性是什么(their computed styles)、每個(gè)節(jié)點(diǎn)在屏幕中的位置是哪里(geometry)。就進(jìn)入了最后一步:?Painting?,按照算出來的規(guī)則,通過顯卡,把內(nèi)容畫到屏幕上。

以上五個(gè)步驟前3個(gè)步驟之所有使用 “Create/Update” 是因?yàn)镈OM、CSSOM、Render Tree都可能在第一次Painting后又被更新,比如JS修改了DOM或者CSS屬性。

Layout 和 Painting 也會(huì)被重復(fù)執(zhí)行,除了DOM、CSSOM更新的原因外,圖片下載完成后也需要調(diào)用Layout 和 Painting來更新網(wǎng)頁。

看Timeline,一目了然

我把扒了一段有贊PC首頁的代碼到本地,通過Node跑起來。Node作為Server端,對(duì)?/js/jquery.js?做了延時(shí)2s返回的處理,并且把?<script src="http://127.0.0.1:8080/js/jquery.js"></script>?放到導(dǎo)航欄的下面,結(jié)果是這樣的:

從上面的Timeline我們可以看出:

  • 首屏?xí)r間和DomContentLoad事件沒有必然的先后關(guān)系
  • 所有CSS盡早加載是減少首屏?xí)r間的最關(guān)鍵
  • js的下載和執(zhí)行會(huì)阻塞Dom樹的構(gòu)建,所以script標(biāo)簽放在首屏范圍內(nèi)的HTML代碼段里會(huì)可能影響首屏的內(nèi)容。
  • 普通script標(biāo)簽放在body底部,做與不做async或者defer處理,都不會(huì)影響首屏?xí)r間,但影響DomContentLoad和load的時(shí)間,進(jìn)而影響依賴他們的代碼的執(zhí)行的開始時(shí)間。

三、問題的答案

回到前面的問題:

script標(biāo)簽的位置會(huì)影響首屏?xí)r間么?

答案是:不影響但有可能截?cái)嗍灼恋膬?nèi)容,使其只顯示上面一部分

四、再進(jìn)一步

所以,總算弄清楚這個(gè)眾所周知的常識(shí)了。但設(shè)計(jì)開發(fā)中可能會(huì)遇到難以把所有的js放到頁面最底部的情形。比如:你的頁面是分模塊來寫的,每一個(gè)模塊都有自己的html、js甚至css,當(dāng)把這些模塊湊到一個(gè)頁面中的時(shí)候就會(huì)出現(xiàn)js自然而然地出現(xiàn)在HTML中間部分。

我們也遇到了這樣的問題,所以就做了一個(gè)開源項(xiàng)目:?Tiny-Loader?—— A small loader that load CSS/JS in best way for page performance 簡(jiǎn)單好用。

回答下題目中所提到的問題,JS一定要放在Body的最底部么? 如果用了Tiny-Loader,JS可以不放在Body最底部。

轉(zhuǎn)載于:https://www.cnblogs.com/xuyuanjia/p/5717071.html

總結(jié)

以上是生活随笔為你收集整理的JS一定要放在Body的最底部么?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。