摘要:阻塞原理瀏覽器內(nèi)核可以分成兩部分渲染引擎或者和引擎。等引擎運(yùn)行完畢,瀏覽器又會(huì)把控制權(quán)還給渲染引擎,繼續(xù)和的構(gòu)建。執(zhí)行時(shí),解析暫停。從加載完成立即執(zhí)行來(lái)看,模式執(zhí)行順序與寫的順序無(wú)關(guān),不保證執(zhí)行順序。
js阻塞原理
瀏覽器內(nèi)核可以分成兩部分:渲染引擎(Layout Engine 或者 Rendering Engine)和 JS 引擎。早期渲染引擎和 JS 引擎并沒有十分明確的區(qū)分,但隨著 JS 引擎越來(lái)越獨(dú)立,內(nèi)核也成了渲染引擎的代稱(下文我們將沿用這種叫法)。渲染引擎又包括了 HTML 解釋器、CSS 解釋器、布局、網(wǎng)絡(luò)、存儲(chǔ)、圖形、音視頻、圖片解碼器等等零部件。
JS 引擎是獨(dú)立于渲染引擎存在的。我們的 JS 代碼在文檔的何處插入,就在何處執(zhí)行。當(dāng) HTML 解析器遇到一個(gè) script 標(biāo)簽時(shí),它會(huì)暫停渲染過(guò)程,將控制權(quán)交給 JS 引擎。JS 引擎對(duì)內(nèi)聯(lián)的 JS 代碼會(huì)直接執(zhí)行,對(duì)外部 JS 文件還要先獲取到腳本、再進(jìn)行執(zhí)行。等 JS 引擎運(yùn)行完畢,瀏覽器又會(huì)把控制權(quán)還給渲染引擎,繼續(xù) CSSOM 和 DOM 的構(gòu)建。 因此與其說(shuō)是 JS 把 CSS 和 HTML 阻塞了,不如說(shuō)是 JS 引擎搶走了渲染引擎的控制權(quán)。
渲染引擎碰到j(luò)s就交出大權(quán)是因?yàn)樗恢纉s的內(nèi)容會(huì)不會(huì)對(duì)接下來(lái)的渲染有沒有影響。但是我們引入js的時(shí)候是知道有沒有影響的,可以根據(jù)具體情況用三種方式之一加載js。
JS的三種加載方式js 有三種加載方式。
正常模式
沒有 defer 或 async,瀏覽器會(huì)立即加載并執(zhí)行指定的腳本,“立即”指的是在渲染該 script 標(biāo)簽之下的文檔元素之前,也就是說(shuō)不等待后續(xù)載入的文檔元素,讀到就加載并執(zhí)行。
async模式
有 async,script.js會(huì)被異步加載,即加載和渲染后續(xù)文檔元素的過(guò)程將和 script.js 的加載并行進(jìn)行(異步)。當(dāng) script.js加載完整立即執(zhí)行script.js。執(zhí)行script.js時(shí),html解析暫停。
從加載完成立即執(zhí)行來(lái)看,async模式 執(zhí)行順序與寫的順序無(wú)關(guān),不保證執(zhí)行順序。
defer 模式
有 defer,script.js會(huì)被異步加載,即加載和渲染后續(xù)文檔元素的過(guò)程將和 script.js 的加載并行進(jìn)行(異步)。這一點(diǎn)與async模式一致。
不同的是當(dāng) script.js加載完成并不會(huì)立即執(zhí)行,而是在所有元素解析完成之后,DOMContentLoaded 事件觸發(fā)之前完成。因此它會(huì)按照寫的順序執(zhí)行。
一圖勝千言: 原圖地址
來(lái)個(gè)demo// htmldefer-async warp
然后 async1.js 文件巨大(到底有多大,我是把jquery的壓縮版拷進(jìn)來(lái)了),然后最后加上 console.log("async1");
文件async2.js 和 normal.js 中分別是 console.log("async2"); 和 console.log("normal");
打開網(wǎng)頁(yè)控制臺(tái)顯示如下: async2 先加載完成就先執(zhí)行了。
而當(dāng)我把 前面引用換成defer時(shí)
同理,defer1.js 里放了jquery的壓縮版源碼。defer2.js里只放了一句日志; 刷新網(wǎng)頁(yè)看下日志:
defer1 、defer2還是按照順序執(zhí)行的。
把a(bǔ)sync、defer都加上,
日志如下:
這個(gè)順序應(yīng)該不是固定的,符合normal最早,defer1會(huì)在 defer2之前的規(guī)矩。 至于async 和 defer的前后則要看本身js的加載以及dom樹的構(gòu)建時(shí)機(jī)吧。
growingwiththeweb 推薦優(yōu)先級(jí)依次是 async defer normal。。
當(dāng)你的js是個(gè)獨(dú)立的模塊且不依賴任何js,使用 async;
如果你的js依賴其他js或者被其他js 依賴,使用 defer;
如果你對(duì)js文件很小且被 async script 依賴,使用正常模式的script且放在async script 前面。
可能的坑雖然理論上defer按加載順序執(zhí)行,但也有同學(xué)反映事實(shí)上并不是這樣。。比如這位同學(xué)的問(wèn)題:
我認(rèn)為這是涉及到 event loop的 task和微任務(wù)了。
"在現(xiàn)實(shí)當(dāng)中,延遲腳本并不一定會(huì)按照順序執(zhí)行,也不一定會(huì)在 DOMContentLoaded 事件觸發(fā)前執(zhí)行,因此最好只包含一個(gè)延遲腳本。" 《JavaScript 高級(jí)程序設(shè)計(jì)(第三版)》如是說(shuō),所以腳本之間有依賴,最好使用一個(gè)異步腳本吧。比如上面同學(xué)那個(gè)問(wèn)題 可以改成這樣.
掘金小冊(cè)
async vs defer
談?wù)剆cript標(biāo)簽
defer async區(qū)別
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/99709.html
摘要:由于始終沒有還原阻塞時(shí)的情形,無(wú)法截圖。寫模擬場(chǎng)景,由于當(dāng)時(shí)的場(chǎng)景是外鏈?zhǔn)羌虞d阻塞,而不是執(zhí)行阻塞,暫時(shí)沒有有效模擬。但是可以確定的是,使用或可以有效解決,外鏈阻塞內(nèi)部執(zhí)行的問(wèn)題。 由于始終沒有還原阻塞時(shí)的情形,無(wú)法截圖。在正常情況下,是無(wú)法區(qū)別是否使用defer的區(qū)別的。后續(xù)看一下是否能模擬場(chǎng)景。寫demo模擬場(chǎng)景,由于當(dāng)時(shí)的場(chǎng)景是外鏈?zhǔn)莏s加載阻塞,而不是js執(zhí)行阻塞,暫時(shí)沒有有效...
摘要:修改瀏覽器渲染因?yàn)榈淖枞沟媒馕鐾V梗螺d完成之前,頁(yè)面無(wú)法顯示任何東西。瀏覽器渲染解析到文件時(shí)出現(xiàn)阻塞。我們把調(diào)整到尾部瀏覽器渲染這是頁(yè)面可以渲染了,但是沒有樣式。 本文示例源代碼請(qǐng)戳github博客,建議大家動(dòng)手敲敲代碼。 前言 瀏覽器渲染頁(yè)面的過(guò)程 從耗時(shí)的角度,瀏覽器請(qǐng)求、加載、渲染一個(gè)頁(yè)面,時(shí)間花在下面五件事情上: DNS 查詢 TCP 連接 HTTP 請(qǐng)求即響應(yīng) 服務(wù)器響...
摘要:修改瀏覽器渲染因?yàn)榈淖枞沟媒馕鐾V梗螺d完成之前,頁(yè)面無(wú)法顯示任何東西。瀏覽器渲染解析到文件時(shí)出現(xiàn)阻塞。我們把調(diào)整到尾部瀏覽器渲染這是頁(yè)面可以渲染了,但是沒有樣式。 本文示例源代碼請(qǐng)戳github博客,建議大家動(dòng)手敲敲代碼。 前言 瀏覽器渲染頁(yè)面的過(guò)程 從耗時(shí)的角度,瀏覽器請(qǐng)求、加載、渲染一個(gè)頁(yè)面,時(shí)間花在下面五件事情上: DNS 查詢 TCP 連接 HTTP 請(qǐng)求即響應(yīng) 服務(wù)器響...
摘要:腳本的無(wú)阻塞加載代碼此處可以放源碼使得該文件變大,以便異步加載時(shí)看效果代碼同步加載輸出和在文檔完成解析后,觸發(fā)事件前執(zhí)行。對(duì)動(dòng)態(tài)嵌入的腳本使用來(lái)達(dá)到類似的效果。是否在允許的情況下異步執(zhí)行該腳本。該屬性對(duì)于內(nèi)聯(lián)腳本無(wú)作用即沒有屬性的腳本。 腳本的無(wú)阻塞加載 moduleA.js 代碼 console.log(Im A); /* 此處可以放jquery源碼 使得該文件變大,以便異步加載時(shí)看...
摘要:例如,當(dāng)解析器被腳本阻塞時(shí),解析器雖然會(huì)停止構(gòu)建,但仍會(huì)識(shí)別該腳本后面的資源,并進(jìn)行預(yù)加載。也就是說(shuō),會(huì)阻塞頁(yè)面的渲染但是,并不會(huì)阻塞的解析。的加載不會(huì)阻塞頁(yè)面的渲染和資源的加載,一旦加載到就會(huì)立刻執(zhí)行。 大家是不是會(huì)遇到這樣的一個(gè)問(wèn)題,頁(yè)面加載速度過(guò)慢,瀏覽器老在轉(zhuǎn)圈圈,頁(yè)面部分內(nèi)容需要花費(fèi)較多的時(shí)間才能加載出來(lái)? 要明白上述問(wèn)題,我們需要知道是什么在阻塞頁(yè)面的渲染? 1、瀏覽器如何...
閱讀 2452·2021-11-15 11:36
閱讀 1192·2019-08-30 15:56
閱讀 2257·2019-08-30 15:53
閱讀 1053·2019-08-30 15:44
閱讀 665·2019-08-30 14:13
閱讀 1010·2019-08-30 10:58
閱讀 488·2019-08-29 15:35
閱讀 1311·2019-08-29 13:58