摘要:的堵塞特性上面引用兩段話的意思大致是,當(dāng)瀏覽器解析文檔時(shí),一旦遇到標(biāo)簽沒(méi)有和屬性就會(huì)立即下載并執(zhí)行,與此同時(shí)瀏覽器對(duì)文檔的解析將會(huì)停止,直到代碼執(zhí)行完成。實(shí)現(xiàn)代碼執(zhí)行代碼缺點(diǎn)是不能跨域請(qǐng)求參考裝載和執(zhí)行元素所著的的第一章
Script 的堵塞(block)特性
Scripts without async or defer attributes, as well as inline scripts, are fetched and executed immediately, before the browser continues to parse the page. - MDN
the blocking nature of JavaScript, which is to say that nothing else can happen while JavaScript code is being executed. In fact, most browsers use a single process for both user interface (UI) updates and JavaScript execution, so only one can happen at any given moment in time. The longer JavaScript takes to execute, the longer it takes before the browser is free to respond to user input. - Nicholas C. Zakas「High Performance JavaScript 」
上面引用兩段話的意思大致是,當(dāng)瀏覽器解析DOM文檔時(shí),一旦遇到 script 標(biāo)簽(沒(méi)有defer 和 async 屬性)就會(huì)立即下載并執(zhí)行,與此同時(shí)瀏覽器對(duì)文檔的解析將會(huì)停止,直到 script 代碼執(zhí)行完成。出現(xiàn)這種堵塞行為一方面是因?yàn)闉g覽器的UI渲染,交互行為等都是單線程操作,另一方是因?yàn)?script 里面的代碼可能會(huì)影響到后面文檔的解析,比如下面的代碼:
html
這個(gè)堵塞特性會(huì)嚴(yán)重的影響用戶體驗(yàn),下面是幾種優(yōu)化方案:
盡量把腳本往文檔的后面放,以減少對(duì)文檔的堵塞,最好放在
前面。
盡量把腳本按照它們的依賴關(guān)系放在一個(gè)文件中
不過(guò)更好的方法是下面的非堵塞加載腳本(Nonblocking Scripts)的方法:
1. Deferred Script (延遲腳本)Script 有一個(gè) defer 屬性,擁有這個(gè)屬性的script表明這個(gè)script不會(huì)修改DOM,因此這段腳本會(huì)在文檔樹(shù)全部解析完成后觸發(fā)( to be executed after the document has been parsed). 但這個(gè)屬性并不被所有的瀏覽器支持。
2. Dynamic Script Elements (動(dòng)態(tài)腳本)原理就是使用腳本創(chuàng)建 script 元素,設(shè)置 src 需為要?jiǎng)討B(tài)添加腳本的 URL,再把這個(gè) script 添加到DOM中。有時(shí)我們需要?jiǎng)討B(tài)腳本加載完成后再執(zhí)行某些操作,這就需要我們?cè)谀_本加載完成后添加一個(gè)回調(diào)函數(shù),這個(gè)可以通過(guò) script 的 onload 事件實(shí)現(xiàn)。下面的實(shí)現(xiàn)代碼:
jsfunction loadJS(url, callback){ var script = document.createElement("script"); script.type = "text/javascript"; if(script.readyState){ // 兼容IE的舊版本 script.onreadystatechange = function(){ if(script.readyState == "loaded" || script.readyState == "complete"){ script.onreadystatechange = null; callback(); } } } else{ script.onload = function(){ callback(); } } script.src = url; document.getElementsByTagName("head")[0].appendChild(script); }
有時(shí)我們需要我們動(dòng)態(tài)加載的腳本按照我們加載的順序執(zhí)行,但上面的實(shí)現(xiàn)并不能保證這一點(diǎn),加載的腳本在下載完成后就會(huì)立即執(zhí)行,而不會(huì)按照我們定義的順序。要解決這個(gè)問(wèn)題也不難,可以參照下面的代碼:
jsloadJS("a.js", function(){ loadJS("b.js", function(){ loadJS("c.js", function(){ app.init(); }) }) })
當(dāng)有大量的腳本需要?jiǎng)討B(tài)添加時(shí),這樣寫也會(huì)遇到問(wèn)題;另外的解決方案是利用一些現(xiàn)成的庫(kù),比如 LABjs
3. XMLHttpRequest Script Injection (XHR動(dòng)態(tài)插入)原理是利用XMLHttpReques(XHR)對(duì)象,動(dòng)態(tài)獲取一段JS代碼,然后插入文檔。
相對(duì)其他方法來(lái)說(shuō)的一個(gè)優(yōu)點(diǎn)是可以“懶執(zhí)行”,也就是JS代碼已經(jīng)先下載好了并沒(méi)有執(zhí)行,可以在需要的來(lái)執(zhí)行(?)(之前的動(dòng)態(tài)腳本在下載后會(huì)立即執(zhí)行)。實(shí)現(xiàn)代碼:
jsfunction xhrLoadJS (url, callback){ var xhr = new XMLHttpRequest(); xhr.open("get", url, true); xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){ var script = document.createElement("script"); script.type = "text/script"; script.text = xhr.responseText; eval(xhr.responseText); // 執(zhí)行代碼 document.body.appendChild(script); callback(); } } } xhr.send(null); }
缺點(diǎn)是不能跨域請(qǐng)求
參考Javascript 裝載和執(zhí)行
MDN Script元素
Nicholas C. Zakas 所著的「High Performance JavaScript 」的第一章 "Loading and Execution"
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/85720.html
摘要:是一款可愛(ài)的小插件,將和瀏覽器的封裝到一起,解決了單純使用進(jìn)行無(wú)刷新加載時(shí)對(duì)搜索引擎的不友好,并且節(jié)省了開(kāi)支提高了瀏覽速度,明顯地優(yōu)化了用戶體驗(yàn)。是提供的,是對(duì)瀏覽器歷史對(duì)象的增強(qiáng)。 showImg(https://segmentfault.com/img/remote/1460000007640529?w=1008&h=569); pjax 是一款可愛(ài)的 jQuery 小插件,將 a...
摘要:是一款可愛(ài)的小插件,將和瀏覽器的封裝到一起,解決了單純使用進(jìn)行無(wú)刷新加載時(shí)對(duì)搜索引擎的不友好,并且節(jié)省了開(kāi)支提高了瀏覽速度,明顯地優(yōu)化了用戶體驗(yàn)。是提供的,是對(duì)瀏覽器歷史對(duì)象的增強(qiáng)。 showImg(https://segmentfault.com/img/remote/1460000007640529?w=1008&h=569); pjax 是一款可愛(ài)的 jQuery 小插件,將 a...
摘要:我把這個(gè)領(lǐng)域的東西寫成了一個(gè)系列,以后還會(huì)繼續(xù)完善下去安全一同源策略與跨域安全二攻擊安全三攻擊 上文說(shuō)完了CSRF攻擊,本文繼續(xù)研究它的兄弟XSS攻擊。 什么是XSS攻擊 XSS攻擊全名(Cross-Site-Script)跨域腳本攻擊,為了跟CSS(Cascading-Style-Sheet)區(qū)分開(kāi)來(lái),所以縮寫是XSS。 XSS攻擊的原理 上一節(jié)說(shuō)道的CSRF攻擊是利用的是偽請(qǐng)求,這...
摘要:我把這個(gè)領(lǐng)域的東西寫成了一個(gè)系列,以后還會(huì)繼續(xù)完善下去安全一同源策略與跨域安全二攻擊安全三攻擊 上文說(shuō)完了CSRF攻擊,本文繼續(xù)研究它的兄弟XSS攻擊。 什么是XSS攻擊 XSS攻擊全名(Cross-Site-Script)跨域腳本攻擊,為了跟CSS(Cascading-Style-Sheet)區(qū)分開(kāi)來(lái),所以縮寫是XSS。 XSS攻擊的原理 上一節(jié)說(shuō)道的CSRF攻擊是利用的是偽請(qǐng)求,這...
摘要:關(guān)于動(dòng)靜分離的描述,這里推薦一篇不錯(cuò)的博文網(wǎng)站靜態(tài)化處理動(dòng)靜分離策略。這里的解決辦法則是采用的屬性,將其應(yīng)用于數(shù)據(jù)請(qǐng)求相關(guān)的上,就可以達(dá)到腳本與數(shù)據(jù)并發(fā)加載的效果。 作者:莫冠釗 轉(zhuǎn)載請(qǐng)注明出處,保留原文鏈接和作者信息 前言 當(dāng)今許多大型網(wǎng)頁(yè)應(yīng)用尤其是SPA均采用了動(dòng)靜分離的策略。關(guān)于動(dòng)靜分離的描述,這里推薦一篇不錯(cuò)的博文 網(wǎng)站靜態(tài)化處理—?jiǎng)屿o分離策略。 本人是做前端的,之前有幸與一...
閱讀 484·2024-11-07 18:25
閱讀 130851·2024-02-01 10:43
閱讀 961·2024-01-31 14:58
閱讀 925·2024-01-31 14:54
閱讀 83048·2024-01-29 17:11
閱讀 3311·2024-01-25 14:55
閱讀 2086·2023-06-02 13:36
閱讀 3207·2023-05-23 10:26