CSS和JS在網(wǎng)頁中的放置順序
- 網(wǎng)站加載的整個完整過程:
- 首先瀏覽器從服務器接收到html代碼悠瞬,然后開始解析html
- 構建DOM樹(自html頂向下進行構建)习贫,并且在同時構建渲染樹
- 遇到JS文件加載執(zhí)行,將阻塞DOM樹的構建垦垂;遇到CSS文件预厌,將阻塞渲染樹的構建
(script標簽中的defer屬性:構建DOM樹的過程和js文件的加載異步(并行)進行建炫,但是js文件執(zhí)行需要在DOM樹構建完成之后。
script標簽中的async屬性:構建DOM樹断盛、渲染樹的過程和js文件的加載和執(zhí)行異步(并行)進行)
- 為何要注意CSS和JS在網(wǎng)頁中的放置順序
- 若CSS樣式放在底部罗洗,對于IE瀏覽器,在點擊鏈接钢猛、輸入URL伙菜、使用書簽進入等情況下,會逐步加載無樣式的內容命迈,等CSS加載后頁面突然會展現(xiàn)樣式贩绕,影響閱讀火的。
- 若JS放在頂部(
<head>
標簽等),會禁用并發(fā)淑倾,阻止其他內容的下載馏鹤,影響頁面加載的速度;如果js文件比較大娇哆,算法也比較復雜的話湃累,影響更大。
白屏和FOUC
- 在寫HTML代碼時碍讨,我們都是將CSS文件的引入位置放在頭部(
<head>
標簽內部)治力,將js文件的引入位置放在底部(</body>
前面)。 - 不同的瀏覽器對于CSS和HTML的處理方式不同勃黍,有的是等待CSS加載完成之后宵统,對HTML元素進行渲染和展示(白屏問題)。有的是先對HTML元素進行展示溉躲,然后等待CSS加載完成之后重新對樣式進行修改(FOUC無樣式內容閃爍)
- 如果把CSS樣式放在底部,對于IE瀏覽器,在某些場景下(新窗口打開,刷新等)頁面會出現(xiàn)白屏,而不是內容逐步展現(xiàn)榜田,如果使用 @import標簽,即使 CSS 放入 link, 并且放在頭部,也可能出現(xiàn)白屏。
- 如果把CSS樣式放在底部,對于IE瀏覽器,在某些場景下(點擊鏈接,輸入URL,使用書簽進入等),會出現(xiàn) FOUC 現(xiàn)象(逐步加載無樣式的內容,等CSS加載后頁面突然展現(xiàn)樣式).對于 Firefox 會一直表現(xiàn)出 FOUC 锻梳。
- 如果把js文件放在頭部箭券,腳本會阻塞后面內容的呈現(xiàn),腳本會阻塞其后組件的下載疑枯,出現(xiàn)白屏問題辩块。
async與defer的作用和區(qū)別
作用
<script src="script.js"></script>
沒有defer或async,瀏覽器會立即加載并執(zhí)行指定的腳本(“立即”指的是在渲染該script標簽之下的文檔之前)荆永,也就是說不等后續(xù)載入的文檔元素废亭,讀到就加載并執(zhí)行。
<script async src="script.js"></script>
有async具钥,加載和渲染后續(xù)文檔元素的過程將和script.js的加載與執(zhí)行并行進行(異步)豆村。
<script defer src="script.js"></script>
有defer,加載后續(xù)文檔元素的過程和script.js的加載并行進行(異步)骂删,但script.js的執(zhí)行要在所有元素解析完成之后掌动,DOMContentLoaded事件觸發(fā)之前完成。區(qū)別
藍色線代表網(wǎng)絡讀取宁玫,紅色線代表執(zhí)行時間粗恢,這倆都是針對腳本的;綠色線代表 HTML 解析欧瘪。
defer 和 async 在網(wǎng)絡讀染焐洹(下載)這塊兒是一樣的,都是異步的(相較于 HTML 解析),它倆的差別在于腳本下載完之后何時執(zhí)行妖碉。
defer:腳本延遲到文檔解析和顯示后執(zhí)行涌庭,有順序。
async:不保證順序嗅绸。
網(wǎng)頁的渲染機制
- 構建DOM樹(DOM tree):從上到下解析HTML文檔生成DOM節(jié)點樹(DOM tree)脾猛,也叫內容樹(content tree);
- 構建CSSOM(CSS Object Model)樹:加載解析樣式生成CSSOM樹鱼鸠;
- 執(zhí)行JavaScript:加載并執(zhí)行JavaScript代碼(包括內聯(lián)代碼或外聯(lián)JavaScript文件)猛拴;
- 構建渲染樹(render tree):根據(jù)DOM樹和CSSOM樹,生成渲染樹(render tree);
渲染樹:按順序展示在屏幕上的一系列矩形蚀狰,這些矩形帶有字體愉昆,顏色和尺寸等視覺屬性。 - 布局(layout):根據(jù)渲染樹將節(jié)點樹的每一個節(jié)點布局在屏幕上的正確位置麻蹋;
- 繪制(painting):遍歷渲染樹繪制所有節(jié)點跛溉,為每一個節(jié)點適用對應的樣式,這一過程是通過UI后端模塊完成扮授;
為了更友好的用戶體驗浑厚,瀏覽器會盡可能快的展現(xiàn)內容闷游,而不會等到文檔所有內容到達才開始解析和構建/布局渲染樹,而是每次處理一部分,并展現(xiàn)在屏幕上震嫉,這也是為什么我們經(jīng)橙勘疲可以看到頁面加載的時候內容是從上到下一點一點展現(xiàn)的售貌。
Webkit渲染引擎流程如下圖: