最新文章專題視頻專題問(wèn)答1問(wèn)答10問(wèn)答100問(wèn)答1000問(wèn)答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
當(dāng)前位置: 首頁(yè) - 科技 - 知識(shí)百科 - 正文

JavaScript無(wú)阻塞加載和defer、async

來(lái)源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 20:24:36
文檔

JavaScript無(wú)阻塞加載和defer、async

JavaScript無(wú)阻塞加載和defer、async:無(wú)阻塞加載把js放在head里,瀏覽器是怎么去執(zhí)行它的呢,是按順序加載還是并行加載呢?在舊的瀏覽器下,都是按照先后順序來(lái)加載的,這就保證了加載的js依賴不會(huì)發(fā)生問(wèn)題。但是少部分新的瀏覽器已經(jīng)開(kāi)始允許并行加載js了,也就是說(shuō)可以同時(shí)下載js文件,但是還是
推薦度:
導(dǎo)讀JavaScript無(wú)阻塞加載和defer、async:無(wú)阻塞加載把js放在head里,瀏覽器是怎么去執(zhí)行它的呢,是按順序加載還是并行加載呢?在舊的瀏覽器下,都是按照先后順序來(lái)加載的,這就保證了加載的js依賴不會(huì)發(fā)生問(wèn)題。但是少部分新的瀏覽器已經(jīng)開(kāi)始允許并行加載js了,也就是說(shuō)可以同時(shí)下載js文件,但是還是
無(wú)阻塞加載

把js放在head里,瀏覽器是怎么去執(zhí)行它的呢,是按順序加載還是并行加載呢?在舊的瀏覽器下,都是按照先后順序來(lái)加載的,這就保證了加載的js依賴不會(huì)發(fā)生問(wèn)題。但是少部分新的瀏覽器已經(jīng)開(kāi)始允許并行加載js了,也就是說(shuō)可以同時(shí)下載js文件,但是還是按先后順序執(zhí)行文件的。

下載是異步的沒(méi)問(wèn)題,但是每個(gè)javascript執(zhí)行的時(shí)候還是同步的,就是先出現(xiàn)的script標(biāo)簽一定是先執(zhí)行,即使是并行下載它是最后一個(gè)下載完成的,除非標(biāo)有defer的script標(biāo)簽。任何javascript在執(zhí)行的時(shí)候都會(huì)中斷當(dāng)前html文檔解析,自然會(huì)阻止頁(yè)面渲染。

javascript加載是不會(huì)影響已經(jīng)渲染的頁(yè)面,但是會(huì)中斷html文檔解析,瀏覽器會(huì)在javascript執(zhí)行以后決定當(dāng)前文檔是否需要進(jìn)行重新渲染或者文檔重排。所以即使javascript放到最后面也會(huì)使瀏覽器暫停,但不影響之前已經(jīng)解析出來(lái)的dom文檔,此時(shí)對(duì)于用戶來(lái)說(shuō)是可操作的。

javascript下載完畢之后會(huì)立即執(zhí)行,所有的javascript執(zhí)行都會(huì)阻塞瀏覽器的其他行為,例如阻塞其他javascript的執(zhí)行、其他的http請(qǐng)求的執(zhí)行以及頁(yè)面的解析和渲染。(html文檔中外部js的下載也會(huì)阻塞瀏覽器的行為,但通過(guò)創(chuàng)建script元素動(dòng)態(tài)js的下載不會(huì),可能是認(rèn)為動(dòng)態(tài)的js不會(huì)改變頁(yè)面效果,所以允許資源并行下載。)

JavaScript無(wú)阻塞加載和defer、async

圖示動(dòng)態(tài)腳本的下載

UI線程會(huì)根據(jù)頁(yè)面里資源(資源是指css文件,圖片等等)書(shū)寫(xiě)的先后順序來(lái)加載資源,加載資源也就是使用http請(qǐng)求獲取資源,像css外部文件,html文件以及圖片等資源http請(qǐng)求處理完畢也就意味著資源加載結(jié)束,但是像外部的javascript文件的加載則不同,它的加載過(guò)程被分為兩步,第一步和加載css文件和圖片一樣,就是執(zhí)行一個(gè)http請(qǐng)求下載外部的js文件,但是javascript完成http操作后并不意味操作完畢,UI線程接著會(huì)執(zhí)行它。js腳本的下載和執(zhí)行必須是一個(gè)完整的操作,是不能被割裂的。動(dòng)態(tài)js的下載不會(huì)阻塞,但執(zhí)行一定會(huì)會(huì)。

瀏覽器為了提升用戶體驗(yàn),加快UI線程的執(zhí)行是一個(gè)無(wú)法回避的問(wèn)題,但是拆分js的下載和執(zhí)行是不可行的,如是乎瀏覽器換了種方式,這個(gè)方式也就是在同一個(gè)時(shí)間能下載多個(gè)資源。

將常用的,穩(wěn)定的靜態(tài)資源統(tǒng)一放在一個(gè)靜態(tài)資源服務(wù)器上,由統(tǒng)一的域名對(duì)外提供,這個(gè)域名要和主體請(qǐng)求的域名不一樣,原理是因?yàn)闉g覽器只通過(guò)域名來(lái)限制連接的個(gè)數(shù),如果一個(gè)頁(yè)面里有兩個(gè)不同的域的,那么并行的http請(qǐng)求個(gè)數(shù)也會(huì)變成兩倍。有度,對(duì)DNS解析要開(kāi)銷,所以2個(gè)最佳。

將所有外部js代碼分為UI初始化代碼和其他代碼,UI初始化代碼是在頁(yè)面加載時(shí)候執(zhí)行的代碼。讓那些不會(huì)用于頁(yè)面初始化展示的js代碼的加載和執(zhí)行操作通過(guò)onload事件在瀏覽器忙指示結(jié)束后觸發(fā),即讓那些和頁(yè)面加載無(wú)關(guān)的js腳本在onload方法里執(zhí)行

無(wú)阻塞加載腳本的核心技術(shù)就是動(dòng)態(tài)的創(chuàng)建script的dom節(jié)點(diǎn),而且可以跨域訪問(wèn)。

動(dòng)態(tài)腳本元素,就是說(shuō) <script> 標(biāo)簽不是寫(xiě)死在HTML中的,而是由現(xiàn)有的腳本生成的,因?yàn)?<script> 標(biāo)簽也是DOM元素的一種,而JavaScript是可以通過(guò)DOM API操作DOM的。動(dòng)態(tài)腳本只有在新建的script元素被添加到html文檔時(shí)開(kāi)始下載,下載完立即執(zhí)行。

無(wú)阻塞腳本的好處就是不會(huì)阻塞UI的執(zhí)行,也不會(huì)影響其他同步j(luò)s代碼的執(zhí)行,不無(wú)阻塞腳本改變了腳本的加載順序,所以在使用無(wú)阻塞腳本時(shí)候一定要更加注意腳本之間的依賴關(guān)系,保證整個(gè)頁(yè)面的腳本都能正常執(zhí)行。

使用無(wú)阻塞腳本了,代碼置于head標(biāo)簽還是html文檔底部也就無(wú)關(guān)緊要了。

頁(yè)面加載的總時(shí)間不是衡量頁(yè)面加載快捷的標(biāo)準(zhǔn),頁(yè)面同步阻塞加載的時(shí)間才是衡量頁(yè)面加載效率的準(zhǔn)確標(biāo)準(zhǔn),非阻塞腳本加載可能會(huì)增加整個(gè)頁(yè)面加載的時(shí)間,但是它可以減少頁(yè)面阻塞加載的時(shí)間。

腳本的異步執(zhí)行,會(huì)產(chǎn)生前后依賴的問(wèn)題。在腳本加載執(zhí)行完畢后,非ie瀏覽器會(huì)觸發(fā)該 <script> 元素的 onload 事件,ie瀏覽器下有onreadystatechange事件,我們可以將回調(diào)放到這個(gè)事件中處理。

每當(dāng)瀏覽器解析到<script>標(biāo)簽(無(wú)論內(nèi)嵌還是外鏈)時(shí),瀏覽器會(huì)優(yōu)先下載、解析并執(zhí)行該標(biāo)簽中的javaScript代碼,而阻塞其后所有頁(yè)面內(nèi)容的下載和渲染。(也就是說(shuō)外部js的下載也會(huì)阻塞別的線程,目前有少部分瀏覽器支持并行下載js)

無(wú)阻塞加載腳本技術(shù)的核心就是:動(dòng)態(tài)下載js腳本的時(shí)候,不會(huì)阻塞UI線程的執(zhí)行。動(dòng)態(tài)腳本為什么不阻塞ui線程?可能是因?yàn)闉g覽器認(rèn)為動(dòng)態(tài)資源不會(huì)影響頁(yè)面渲染。

讓script延遲和異步的兩個(gè)屬性:defer和async

js腳本會(huì)改變文檔輸入流的內(nèi)容,所以執(zhí)行js時(shí)會(huì)暫停頁(yè)面的渲染。對(duì)于內(nèi)聯(lián)腳本沒(méi)什么問(wèn)題,因?yàn)槟_本和html文檔被同時(shí)加載了。但對(duì)于外部引入的腳本,腳本的下載(取決于網(wǎng)速)也會(huì)阻塞瀏覽器文檔的解析和渲染,甚至?xí)枞行g覽器下載別的資源(目前有些瀏覽器已經(jīng)實(shí)現(xiàn)并行下載)。所以出現(xiàn)defer和async屬性,優(yōu)化頁(yè)面的顯示。

defer(延遲)是html4.0中定義的,該屬性使得瀏覽器能延遲腳本的下載,等document文檔載入和解析完成后,按照他們?cè)谖臋n中出現(xiàn)順序再去下載解析。也就是說(shuō)defer屬性的<script>就類似于將<script>放在body底部的效果,會(huì)在document的DOMContentLoaded事件之前執(zhí)行。

將腳本放在body底部比給腳本增加defer屬性讓腳本延遲加載更好。

async(異步)是HTML5新增的屬性,該屬性的作用是讓瀏覽器能并行下載腳本且不阻塞瀏覽器的文檔解析和渲染,下載完成后腳本立即執(zhí)行,可能無(wú)序執(zhí)行,取決于下載完成的時(shí)間)

若瀏覽器同時(shí)支持上述兩種屬性且script標(biāo)簽同時(shí)具有這兩種屬性,則async屬性會(huì)優(yōu)于defer生效。

在不支持async屬性的瀏覽器里,可以通過(guò)動(dòng)態(tài)創(chuàng)建script元素并插入文檔中,實(shí)現(xiàn)腳本的異步載入和執(zhí)行:

JavaScript無(wú)阻塞加載和defer、async

requirejs就是使用這個(gè)方法實(shí)現(xiàn)的。

更多JavaScript無(wú)阻塞加載和defer、async相關(guān)文章請(qǐng)關(guān)注PHP中文網(wǎng)!

聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

JavaScript無(wú)阻塞加載和defer、async

JavaScript無(wú)阻塞加載和defer、async:無(wú)阻塞加載把js放在head里,瀏覽器是怎么去執(zhí)行它的呢,是按順序加載還是并行加載呢?在舊的瀏覽器下,都是按照先后順序來(lái)加載的,這就保證了加載的js依賴不會(huì)發(fā)生問(wèn)題。但是少部分新的瀏覽器已經(jīng)開(kāi)始允許并行加載js了,也就是說(shuō)可以同時(shí)下載js文件,但是還是
推薦度:
標(biāo)簽: 加載 js 阻塞
  • 熱門焦點(diǎn)

最新推薦

猜你喜歡

熱門推薦

專題
Top