1. CSS和JS在網(wǎng)頁(yè)中的放置順序是怎樣的?
CSS必須是在html之前載入,所以放在head標(biāo)簽里。
JS放在CSS后面,既可以放在head標(biāo)簽里,也可以放在body標(biāo)簽之后
2. 解釋白屏和FOUC
- 白屏問(wèn)題: 如果把樣式放在底部,對(duì)于IE瀏覽器,chrome等(css全部加載后再呈現(xiàn),有可能等待長(zhǎng)),在某些場(chǎng)景下(新窗口打開(kāi),刷新等)頁(yè)面會(huì)出現(xiàn)白屏,而不是內(nèi)容逐步展現(xiàn)。使用 @import 標(biāo)簽,即使 CSS 放入 link, 并且放在頭部,也可能出現(xiàn)白屏。 對(duì)于圖片和CSS, 在加載時(shí)會(huì)并發(fā)加載(如一個(gè)域名下同時(shí)加載兩個(gè)文件)。 但在加載 JavaScript 時(shí),會(huì)禁用并發(fā),并且阻止其他內(nèi)容的下載. 所以把 JavaScript 放入頁(yè)面頂部也會(huì)導(dǎo)致 白屏 現(xiàn)象.
- FOUC: Flash of Unstyled Content "無(wú)樣式內(nèi)容閃爍“:有些瀏覽器是邊渲染邊呈現(xiàn),CSS放置body標(biāo)簽底部,會(huì)出現(xiàn)加載html結(jié)束后才一次性加載css樣式,從而導(dǎo)致頁(yè)面閃爍。
我們了解當(dāng)輸入網(wǎng)址按回車后瀏覽器會(huì)向服務(wù)器發(fā)送請(qǐng)求,然后服務(wù)器返回頁(yè)面給瀏覽器,瀏覽器邊下載頁(yè)面邊解析邊渲染。邊下載頁(yè)面邊解析邊渲染的過(guò)程:
- 邊下載邊解析就是邊下載html邊構(gòu)建DOM Tree;
- 瀏覽器以u(píng)ser agent stylesheet(瀏覽器內(nèi)置樣式)為原料構(gòu)建CSSOM Tree;
- DOM Tree+CSSOM Tree構(gòu)建出Render Tree,然后頁(yè)面內(nèi)容渲染出來(lái);
- 當(dāng)解析到inline stylesheet 或 internal stylesheet時(shí),馬上刷新CSSOM Tree,CSSOM Tree或DOM Tree發(fā)生變化時(shí)會(huì)引起Render Tree變化;
- 當(dāng)解析到external stylesheet時(shí)就先加載,然后如internal stylesheet那樣解析和刷新CSSOM Tree和Render Tree了。
總結(jié):上述步驟5中由于樣式文件存在下載這個(gè)延時(shí)不確定的階段,因此網(wǎng)絡(luò)環(huán)境不好或樣式資源體積大的情況下我們可以看到樣式閃爍明顯。
3. async和defer的作用是什么?有什么區(qū)別
- 沒(méi)有 defer 或 async,瀏覽器會(huì)立即加載并執(zhí)行指定的腳本,“立即”指的是在渲染該 script 標(biāo)簽之下的文檔元素之前,也就是說(shuō)不等待后續(xù)載入的文檔元素,讀到就加載并執(zhí)行。
- 有 async,加載和渲染后續(xù)文檔元素的過(guò)程將和 script.js 的加載與執(zhí)行并行進(jìn)行(異步)。
- 有 defer,加載后續(xù)文檔元素的過(guò)程將和 script.js 的加載并行進(jìn)行(異步),但是 script.js 的執(zhí)行要在所有元素解析完成之后,DOMContentLoaded 事件觸發(fā)之前完成。
- 如果腳本涉及少量DOM操作,則defer屬性更優(yōu):因?yàn)閔tml解析未完成前,可能DOM tree未形成,此時(shí)進(jìn)行DOM操作,可能失敗。
如果是多個(gè)腳本,則其執(zhí)行順序?yàn)椋?br> a、多個(gè)defer腳本,根據(jù)HTML5的規(guī)定,會(huì)按照定義的加載順序,按序執(zhí)行;
b、多個(gè)async腳本,由于加載完成立即執(zhí)行,所以是亂序;因此其更適合腳本之間無(wú)依賴關(guān)系的情況。 - 然后從實(shí)用角度來(lái)說(shuō)呢,首先把所有腳本都丟到 </body> 之前是最佳實(shí)踐,因?yàn)閷?duì)于舊瀏覽器來(lái)說(shuō)這是唯一的優(yōu)化選擇,此法可保證非腳本的其他一切元素能夠以最快的速度得到加載和解析。
4. 簡(jiǎn)述網(wǎng)頁(yè)的渲染機(jī)制
瀏覽器將從服務(wù)器獲取的HTML文檔構(gòu)建成文檔對(duì)象模型DOM(Document Object Model).
樣式將被載入和解析,構(gòu)成層疊樣式表模型CSSOM(CSS Object Model).
在DOM和CSSOM之上,渲染樹(shù)(rendering tree)將會(huì)被創(chuàng)建,代表一系列將被渲染的對(duì)象(這在Webkit內(nèi)核中被稱為renderer或者渲染對(duì)象render object,在Gecko內(nèi)核中被稱為框架frame)。渲染樹(shù)映射除了不可見(jiàn)元素(例如<head>或者含有display:none;的標(biāo)簽)外的所有DOM結(jié)構(gòu)。每一段文本字符串都將劃分在不同的渲染對(duì)象中,每一個(gè)渲染對(duì)象都包含了它相應(yīng)的DOM對(duì)象以及計(jì)算后的樣式。換句話講,渲染樹(shù)是DOM的直觀表示。
渲染樹(shù)的每個(gè)元素包含的內(nèi)容都是計(jì)算過(guò)的,它被稱之為布局layout.瀏覽器使用一種流式處理的方法,只需要一次pass繪制操作就可以布局所有的元素(tables需要多次pass繪制,pass表示像素處理和頂點(diǎn)處理)。
最后布局完成,渲染樹(shù)將轉(zhuǎn)化為屏幕上的實(shí)際內(nèi)容,這一步被稱為繪制painting.