(題圖:梵高-向日葵)
我們最開始學(xué)前端的時(shí)候都會(huì)看到教程在處理外部css,js的時(shí)候會(huì)將css放在header中,js放在body的最后。為什么要這樣子處理,今天參考一些資料好好分析下。
為什么外鏈css為什么要放頭部?
首先整個(gè)頁面展示給用戶會(huì)經(jīng)過html 的解析與渲染過程。
而外鏈css無論放在html的任何位置都不影響html的解析,但是影響html的渲染。
如果將css放在尾部,html的內(nèi)容可以第一時(shí)間顯示出來,但是會(huì)阻塞html行內(nèi)css的渲染。
瀏覽器的這個(gè)策略其實(shí)很明智的,想象一下,如果沒有這個(gè)策略,頁面首先會(huì)呈現(xiàn)出一個(gè)行內(nèi)css樣式,待CSS下載完之后又突然變了一個(gè)模樣。用戶體驗(yàn)可謂極差,而且渲染是有成本的。
如果將css放在頭部,css的下載解析是可以和html的解析同步進(jìn)行的,放到尾部,要花費(fèi)額外時(shí)間來解析CSS,并且瀏覽器會(huì)先渲染出一個(gè)沒有樣式的頁面,等CSS加載完后會(huì)再渲染成一個(gè)有樣式的頁面,頁面會(huì)出現(xiàn)明顯的閃動(dòng)的現(xiàn)象。
為什么script要放在尾部?
因?yàn)楫?dāng)瀏覽器解析到script的時(shí)候,就會(huì)立即下載執(zhí)行,中斷html的解析過程,如果外部腳本加載時(shí)間很長(比如一直無法完成下載),就會(huì)造成網(wǎng)頁長時(shí)間失去響應(yīng),瀏覽器就會(huì)呈現(xiàn)“假死”狀態(tài),這被稱為“阻塞效應(yīng)”。
具體的流程是這樣的:
* 瀏覽器一邊下載HTML網(wǎng)頁,一邊開始解析。
* 解析過程中,發(fā)現(xiàn)script標(biāo)簽
* 暫停解析,網(wǎng)頁渲染的控制權(quán)轉(zhuǎn)交給JavaScript引擎
* 如果script標(biāo)簽引用了外部腳本,就下載該腳本,否則就直接執(zhí)行
* 執(zhí)行完畢,控制權(quán)交還渲染引擎,恢復(fù)往下解析HTML網(wǎng)頁
外鏈的script包含async或者defer如何處理?
這兩個(gè)屬性只是script標(biāo)簽在header標(biāo)簽中使用的,如果你把它放在body后面是無效的。
script 的這兩個(gè)屬性主要用于其js文件沒有操作DOM的情況,這時(shí)候就可以將該js腳本設(shè)置為異步加載,通過async或defer來標(biāo)記代碼。
async和defer的區(qū)別:
0、async和defer都僅對外部腳本有效,對于內(nèi)置而不是連接外部腳本的script標(biāo)簽,以及動(dòng)態(tài)生成的script標(biāo)簽不起作用。
1、async和defer雖然都是異步的,不過使用async標(biāo)志的腳本文件一旦加載完成就會(huì)立即執(zhí)行;而使用defer標(biāo)記的腳本文件,會(huì)在
DOMContentLoaded 事件之前(也就是頁面DOM加載完成時(shí))執(zhí)行。
2、如果有多個(gè)js腳本文件,async標(biāo)記不保證按照書寫的順序執(zhí)行,哪個(gè)腳本先下載結(jié)束,就先執(zhí)行那個(gè)腳本。而defer標(biāo)記則會(huì)按照js腳本書寫順序執(zhí)行。
3、一般來說,如果腳本之間沒有依賴關(guān)系,就使用async屬性,如果腳本之間有依賴關(guān)系,就使用defer屬性。如果同時(shí)使用async和defer屬性,后者不起作用,瀏覽器行為由async屬性決定。
對于async標(biāo)記,瀏覽器的解析過程是這樣的:
*
瀏覽器開始解析HTML網(wǎng)頁
*
解析過程中,發(fā)現(xiàn)帶有async屬性的script標(biāo)簽
*
瀏覽器繼續(xù)往下解析HTML網(wǎng)頁,同時(shí)并行下載script標(biāo)簽中的外部腳本
*
腳本下載完成,瀏覽器暫停解析HTML網(wǎng)頁,開始執(zhí)行下載的腳本
*
腳本執(zhí)行完畢,瀏覽器恢復(fù)解析HTML網(wǎng)頁
對于defer標(biāo)記,瀏覽器的解析過程是這樣的:
*
瀏覽器開始解析HTML網(wǎng)頁
*
解析過程中,發(fā)現(xiàn)帶有defer屬性的script標(biāo)簽
*
瀏覽器繼續(xù)往下解析HTML網(wǎng)頁,同時(shí)并行下載script標(biāo)簽中的外部腳本
*
瀏覽器完成解析HTML網(wǎng)頁,此時(shí)再執(zhí)行下載的腳本
由于使用了async或defer的script會(huì)放在header中,而header又會(huì)存在外鏈css,那么二者有順序要求嗎?
header中script和外鏈css的位置順序
先說結(jié)論:
如果在html的header中同時(shí)有js腳本和外鏈css,js腳本最好放外鏈css前面。
其實(shí)js的執(zhí)行是依賴css樣式的。即只有css樣式全部下載完成后才會(huì)執(zhí)行js。
因?yàn)槿绻_本的內(nèi)容是獲取元素的樣式,寬高等CSS控制的屬性,瀏覽器是需要計(jì)算的,也就是依賴于CSS。瀏覽器無法感知腳本內(nèi)容到底是什么,為避免樣式獲取錯(cuò)誤,因而只好等前面所有的樣式下載完后,再執(zhí)行JS。
但是如果css下載事件很長的話,js也無法正常運(yùn)行,導(dǎo)致html無法正常解析出來。如果css的內(nèi)容下載更快的話,是沒影響的,但反過來的話,JS就要等待了,然而這些等待的時(shí)間是完全不必要的。
(啾咪 ^.<)
熱門工具 換一換