(題圖:梵高-向日葵)


          我們最開始學(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í)間是完全不必要的。

          (啾咪 ^.<)


          友情鏈接
          ioDraw流程圖
          API參考文檔
          OK工具箱
          云服務(wù)器優(yōu)惠
          阿里云優(yōu)惠券
          騰訊云優(yōu)惠券
          京東云優(yōu)惠券
          站點(diǎn)信息
          問題反饋
          郵箱:[email protected]
          QQ群:637538335
          關(guān)注微信

                91国际精品 | 黄色片黄色片黄色片黄色片黄色片黄色片 | 色色视频香蕉久久 | 国产一区二三区 | 国产真实乱婬A片三区高清蜜臀 |