高性能的javascript之加載順序與執(zhí)行原理篇
前言
javascript在瀏覽器中的性能,可以認(rèn)為是開發(fā)者所面臨的最嚴(yán)重的可用性問題,今天,自己看完高性能的javascript的加載和執(zhí)行這一章,聊聊怎么解決js的加載順序和執(zhí)行的原理,下面話不多說了,來一起看看詳細(xì)的介紹:
當(dāng)瀏覽器遇到<script>標(biāo)簽的時(shí)候,瀏覽器必須先話時(shí)間下載外鏈的文件然后并執(zhí)行,在這過程中,頁面渲染和用戶交互是完全被阻塞的。
腳本放在哪里比較好?
這種情況無疑是存在嚴(yán)重的性能問題的,由于腳本會(huì)阻塞頁面的渲染,直到它們?nèi)肯螺d并執(zhí)行完成后,頁面渲染才會(huì)繼續(xù),下面的圖就是代碼的執(zhí)行順序
第一個(gè)js文件下載,要等到第一個(gè)js文件下載完全才會(huì)執(zhí)行第二個(gè)js文件,不過現(xiàn)在IE8,F(xiàn)irefox3.5,Safari4和Chrome2都允許并行下載js文件,遺憾的是,js下載過程還是會(huì)阻塞其他資源的下載,例如:圖片
所以提高性能的方法之一:將腳本放在body底部
組織腳本
由于每個(gè)<script>標(biāo)簽下載時(shí)都會(huì)阻塞頁面的渲染,所以減少頁面包含的<script>標(biāo)簽數(shù)量是必不可少的,解決方法:可以把多個(gè)js文件合并打包成一個(gè)js文件,這樣子做的好處就是可以最小化延遲時(shí)間將會(huì)明顯的改善頁面的總體性能,除此之外,還可以減少HTTP的請求。
一般來說下載單個(gè)100KB的文件比下載4個(gè)25KB的文件快。
如果有多個(gè)外鏈的js文件,可以合并成一個(gè)js文件
無阻塞的腳本
盡管下載單個(gè)較大的js文件只產(chǎn)生一次HTTP的請求,但是會(huì)假死瀏覽器一大段時(shí)間,為了避免這種情況,你需要向頁面中逐步加載js文件。
延遲的腳本
defer屬性指明本元素所含的腳本可以延遲執(zhí)行,但是只有IE4+和Firefox3.5+的瀏覽器支持
簡單來說defer的機(jī)制就是知道DOM加載完成前才去下載js文件,不會(huì)阻塞瀏覽器的其他進(jìn)程
在不支持defer屬性的瀏覽器彈出的順序是:defer,script,load
支持defer屬性的瀏覽器彈出的順序是:script,defer,load
所以說defer是在onload事件執(zhí)行之前被調(diào)用
動(dòng)態(tài)腳本
動(dòng)態(tài)腳本的注入有兩種方式,第一就是動(dòng)態(tài)創(chuàng)建script標(biāo)簽,第二就是通過XMLHttpRequest注入頁面
先說說第一種怎么使用:
這種技術(shù)的重點(diǎn)在于:無論在何時(shí)啟動(dòng)下載,文件的下載和執(zhí)行過程不會(huì)阻塞頁面其他進(jìn)程,但是使用動(dòng)態(tài)腳本節(jié)點(diǎn)下載js文件時(shí),返回的代碼會(huì)立即執(zhí)行(除了Firefox和Opera,它們會(huì)等待此前所有動(dòng)態(tài)腳本節(jié)點(diǎn)執(zhí)行完畢)
在主流的瀏覽器會(huì)在<script>標(biāo)簽接收完成時(shí)觸發(fā)一個(gè)load事件,但是ie瀏覽器沒有,所以我們必須封裝一個(gè)兼容所有的瀏覽器都可以使用的方法
這種方式的缺點(diǎn)就是要清楚文件的加載順序,當(dāng)js文件多了,依賴關(guān)系復(fù)雜的時(shí)候,很難管理加載的依賴順序
就像這樣子寫的代碼很難維護(hù)
第二種動(dòng)態(tài)創(chuàng)建腳本方式
實(shí)際上相當(dāng)于創(chuàng)建一個(gè)帶有內(nèi)聯(lián)腳本的<script>標(biāo)簽,一旦新創(chuàng)建的<script>元素被添加到頁面,代碼就會(huì)立即執(zhí)行然后準(zhǔn)備就緒。
優(yōu)點(diǎn):就是下載的js代碼但是不立即執(zhí)行,這樣子可以把腳本的執(zhí)行推遲到你準(zhǔn)備好的時(shí)候執(zhí)行,這種方法還可以兼容所有的瀏覽器
缺點(diǎn):js文件必須與所請求的頁面處于相同的域,js文件不能從CDN下載,一般大型web應(yīng)用都不會(huì)使用這種方式
推薦使用無阻塞模式:
先添加動(dòng)態(tài)所需的代碼,然后假裝初始化頁面的剩下的代碼
[圖片上傳失敗...(image-dd3f9-1515902024710)]
上面介紹了那么多,給大家推薦一些動(dòng)態(tài)延遲加載的庫
有YUI3,LazyLoad和LABjs等這些庫,個(gè)人覺得LABjs庫比較好用,但是沒有用過,大家可以去了解一下,使用方法就不在這里說了。
總結(jié):
提高js性能的幾個(gè)方面
1.</body>閉合標(biāo)簽之前,將所有的<script>標(biāo)簽放到頁面底部。這能確保在腳本執(zhí)行前頁面已經(jīng)完成了渲染
2.合并腳本。頁面中的<script>標(biāo)簽越少,加載也就越快,響應(yīng)也更快。無論外鏈文件還是內(nèi)嵌腳本都是如此
3.有多種無阻塞下載js的方法
3.1使用<script>標(biāo)簽的defer屬性
3.2使用動(dòng)態(tài)創(chuàng)建的<script>元素來下載并執(zhí)行代碼
3.3使用XHR對象下載js代碼并注入頁面中
通過以上策略,可以極大提高那些需要使用大量js的web應(yīng)用的實(shí)際性能
好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
深入理解JavaScript系列(36):設(shè)計(jì)模式之中介者模式詳解
這篇文章主要介紹了深入理解JavaScript系列(36):設(shè)計(jì)模式之中介者模式詳解,中介者模式(Mediator)是指用一個(gè)中介對象來封裝一系列的對象交互,需要的朋友可以參考下2015-03-03JavaScript函數(shù)的調(diào)用以及參數(shù)傳遞
這篇文章主要介紹了JavaScript函數(shù)的調(diào)用以及參數(shù)傳遞,是JavaScript入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-10-10Javascript實(shí)現(xiàn)異步編程的過程
這篇內(nèi)容詳細(xì)分析了Javascript實(shí)現(xiàn)異步編程的過程以及原理解釋,對此知識(shí)點(diǎn)有興趣的朋友可以學(xué)習(xí)下。2018-06-06零基礎(chǔ)學(xué)JavaScript最新動(dòng)畫教程+iso光盤下載
2008-01-01JavaScript預(yù)解析之變量預(yù)解析和函數(shù)預(yù)解析
這篇文章主要介紹了JavaScript預(yù)解析之變量預(yù)解析和函數(shù)預(yù)解析的相關(guān)資料,需要的朋友可以參考下2022-07-07