CSS和JS在網(wǎng)頁(yè)中的放置順序是怎樣的?
-
JS一般放置在</body>標(biāo)簽之前或添加defer屬性
- JS是阻塞加載,會(huì)阻塞DOM樹或阻塞渲染樹的構(gòu)建。
- JS 可能會(huì)修改 DOM,如果在DOM樹加載完成前修改DOM會(huì)導(dǎo)致JS代碼無(wú)效。
- JS可能會(huì)通過(guò)操作DOM對(duì)象的class來(lái)改變DOM,因此必須保證CSS在JS之前加載和解析完成。
-
CSS一般放置在head標(biāo)簽內(nèi)
由于Render Tree是由DOM樹和CSSOM樹組合成的,html頁(yè)面需要等到CSS解析完后才能完成渲染,所以CSS應(yīng)放在head標(biāo)簽內(nèi),優(yōu)先下載解析,以避免頁(yè)面元素由于樣式缺失造成瞬間的白頁(yè)或者給用戶閃爍感。
白屏和FOUC
- 當(dāng)把CSS樣式放在底部或者使用@import方式引入樣式、或?qū)S放在頭部造成其他內(nèi)容阻塞加載時(shí):
- 一些瀏覽器例如chrome,他的加載和渲染機(jī)制是等頭部的JS和底部的CSS全部加載解析完后再渲染展示頁(yè)面,而這個(gè)等待的時(shí)間就為白屏。
- 另一些瀏覽器例如Firefox,他會(huì)在CSS未加載前先展現(xiàn)頁(yè)面,等css加載后再重繪一次,這就造成了FOUC (無(wú)樣式內(nèi)容閃爍)。
async和defer的作用是什么?有什么區(qū)別
- 當(dāng)瀏覽器碰到<script>標(biāo)簽時(shí):
- 瀏覽器會(huì)立即加載并執(zhí)行指定的腳本,并且阻塞后續(xù)的頁(yè)面渲染。
- 有 async時(shí),加載和渲染后續(xù)文檔元素的過(guò)程將和 js腳本 的加載與執(zhí)行并行進(jìn)行(異步)。有 async 的情況下,JavaScript 腳本一旦下載好了就會(huì)執(zhí)行,所以很有可能不是按照原本的順序來(lái)執(zhí)行的。如果 JavaScript 腳本前后有依賴性,使用 async 就很有可能出現(xiàn)錯(cuò)誤。
- 有 defer時(shí),加載后續(xù)文檔元素的過(guò)程將和 js腳本 的加載并行進(jìn)行(異步),但是 js腳本 的執(zhí)行要在DOM加載完成之后,DOMContentLoaded 事件觸發(fā)之前完成。
簡(jiǎn)述網(wǎng)頁(yè)的渲染機(jī)制
- 解析html構(gòu)建DOM樹
- 解析CSS構(gòu)建CSSOM樹
- 把DOM和CSSOM組合成渲染樹(Render Tree)
- 在渲染樹的基礎(chǔ)上進(jìn)行布局,計(jì)算每個(gè)節(jié)點(diǎn)的幾何結(jié)構(gòu)(Layout Tree)
- 把每個(gè)節(jié)點(diǎn)繪制到屏幕上(Painting)