在構建頁面時,我們會在html中載入一個或多個css和js文件。或許大家都已經習慣了“最佳實踐”中,css文件應該放在<head>標簽中引入,而js文件則是放在</body>關閉標簽前引入的原則,但其中的原因,很多人可能像我之前一樣,不是瞭解得很清楚。在查閱了書籍和資料後,稍微瞭解的其中的原由。 讓 ...
在構建頁面時,我們會在html中載入一個或多個css和js文件。或許大家都已經習慣了“最佳實踐”中,css文件應該放在<head>標簽中引入,而js文件則是放在</body>關閉標簽前引入的原則,但其中的原因,很多人可能像我一樣,不是瞭解得很清楚。在查閱了書籍和資料後,稍微瞭解的其中的原由。
讓我們先看一看瀏覽器中的渲染流程:
主流程:
詳細流程:
當瀏覽器獲得一個html文件時,會“自上而下”
載入,併在載入過程中進行解析渲染。
步驟:
- 瀏覽器將HTML解析成一個DOM Tree,DOM Tree的構建過程是一個深度遍歷過程:當前節點的所有子節點都構建好後才會去構建當前節點的下一個兄弟節點。
- 將CSS解析成 CSS Rule Tree 。
- 根據DOM樹和CSSOM合併構造 Render Tree(渲染樹)。
- (註意:Render Tree 並不等同於 DOM 樹,一些像 <head> 或 display:none 的元素不會放進渲染樹)
- Layout,即佈局階段,顧名思義就是計算出每個節點在屏幕中的位置。因為有了Render Tree,瀏覽器已經能知道網頁中有哪些節點、各個節點的CSS定義以及他們的從屬關係。
- 最後是繪製,瀏覽器遍歷Render Tree,使用UI後端層繪製Render Tree節點到屏幕。最終,我們就可以在屏幕上看到文檔的內容。
整個瀏覽器渲染頁面的流程就是這樣,可以說正是因為這個渲染的過程,決定了我們html文檔中css文件和js文件的引入位置。
在html中,css文件一般是由href載入,而js用src載入,這兩者有什麼不同呢?
href:是hypertext reference的縮寫,表示超文本引用,用來建立當前元素和文檔間的鏈接。常用的有link,a。
src:是source的縮寫,表示資源,src指向的內容會嵌入到文檔中當前標簽的位置。常用的有img, script, iframe。
當css使用href引用時,當瀏覽器解析到該元素時,css文件會並行下載,不會阻塞DOM樹的解析
當js使用src引用時,當瀏覽器解析到該元素時,會阻塞對文檔和解析和渲染以及資源的下載,等待js文件的下載、解析和執行。直到腳本全部執行完畢,瀏覽器才會繼續解析和渲染文檔
為什麼腳本會阻塞文檔的解析和渲染?
因為腳本有直接操作DOM節點和樣式的能力,例如 document.write,這意味著,在JS執行完成前,所有的資源載入解析可能是沒有必要的
OK,瞭解了以上原因,現在應該可以理解為什麼要將css放在頭部而js放在底部引入了:
css在頭部引入:在生成DOM Tree的同時,就可以同時對DOM Tree進行渲染,使頁面更快的呈現在屏幕上。如果css放在底部引入,那麼在DOM Tree已經生成完畢之後,還需要等待css文件的下載和解析,之後才能進行渲染並繪製,這樣會導致頁面長時間白屏。
js在底部引入:不會阻塞文件的載入和解析,在頁面渲染完畢時才載入執行,不影響用戶的瀏覽