前端性能----資源加載順序


渲染事件

           

  1. **domLoading **表示開始解析第一批收到的 HTML 文檔的字節
  2. **domInteractive **表示完成全部 HTML 的解析並且 DOM 構建完畢
  3. **domContentLoaded **表示 DOM 與 CSSOM 皆已准備就緒
  4. **domComplete **表示所有的處理都已完成並且所有的附屬資源都已經下載完畢
  5. **loadEvent **作為網頁加載的最后一步以便觸發附加的應用邏輯

CSS阻塞

CSS會阻塞渲染樹的構建,不阻塞DOM構建,但是在CSSOM構建完成之前,頁面不會開始渲染(一片空白),與js不一樣,js雖然會阻塞后續DOM構建,但是前面已經就緒的內容會進行渲染。CSS雖然不阻塞DOM構建,但是會阻塞后面js的執行,從而間接阻塞完整DOM的構建,舉個例子:

在資源服務器端,設定css和js的返回延時,且js先返回,css后返回,但是文檔中,css在js之前:

app.use('/css/:cssName',(req,res)=>{ let fileName = req.params.cssName; setTimeout(()=>{ res.sendFile(fileName,{ root: path.join(__dirname,'../css') }); },4000); }); app.use('/js/:jsName',(req,res)=>{ let fileName = req.params.jsName; setTimeout(()=>{ res.sendFile(fileName,{ root: path.join(__dirname,'../js') }); },2000); })

然后html:

<!DOCTYPE html>
<html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <link rel="stylesheet" href="/css/animateTop.css"> </head> <body> <p>body content before script</p> <script type="text/javascript" src="/js/script1.js"></script> <script type="text/javascript" src="/js/script2.js"></script> <script type="text/javascript" src="/js/script3.js"></script> <p>body after script</p> </body> </html>

測試發現,后邊的js雖然先下載下來,但是只有等css執行完畢后,才得到執行。

然后進一步js又會阻塞后續DOM樹構建,就這樣導致整個渲染過程話費更多時間。所以我們要盡快加載CSS並構建CSSOM。

針對性優化

  • 盡早加載css文件並生成CSSOM.
  • 不使用@import
  • 利用媒體查詢,處理特定設備下的CSS,以減少不必要的阻塞.

JS阻塞

JS默認也是會阻塞DOM和渲染樹的構建的。HTML解析器在遇到腳本文件時,默認為停下來去獲取腳本(不考慮資源預加載優化),然后執行,期間阻塞DOM構建。

defer腳本

聲明為defer的腳本會延遲到DOM構建完成后(DOMInteractive事件),DOMContentLoadedwindow.onload事件之前執行(但依然會被瀏覽器的預加載策略提前下載)。只針對外聯腳本有效。多個defer會按照先后順序串行執行。

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script type="text/javascript" src="/js/script1.js" defer></script> <script defer> console.log('inserted'); </script> </head> <body> <script type="text/javascript" src="/js/script2.js"></script> <p>conten after script</p> <script> document.addEventListener("DOMContentLoaded", function() { console.log('DOMContentLoaded'); }, false); window.addEventListener('load', function() { console.log('window loaded'); }, false); </script> </body> </html>

我們在控制台會看到先執行script2.js其后面的p標簽渲染沒有受到阻塞。內聯腳本按照正常順序執行,依然阻塞DOM。它們都在DOMContentLoadedwindow.onload事件之前執行。

async腳本

聲明 為異步的腳本會異步地下載和執行,會在window.onload事件之前執行,但是可能會在DOMContenLoaded事件前后執行。

一張圖:

 圖片來源:http://blog.csdn.net/liuhe688/article/details/51247484

實際上上面的圖並不完全正確。現代瀏覽器對腳本和樣式資源還會有預加載策略。這個后面會講。

多個defer和async腳本

當我們不使用defer和async,我們會看到現代瀏覽器的資源預加載策略會並行地下載多個腳本和樣式文件:

<!DOCTYPE html>
<html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <link rel="stylesheet" href="/css/animateTop.css"> </head> <body> <script type="text/javascript" src="/js/script1.js"></script> <script type="text/javascript" src="/js/script2.js"></script> <script type="text/javascript" src="/js/script3.js"></script> <p>conten after script</p> </body> </html>

資源加載順序:

我們看到各個樣式和腳本文件都是並行下載的,這得益於瀏覽器的資源預加載。

而當我們加入多個defer或者async時,情況有所變化,注意查看三個腳本的屬性:

<!DOCTYPE html>
<html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <link rel="stylesheet" href="/css/animateTop.css"> </head> <body> <script type="text/javascript" src="/js/script1.js" async></script> <script type="text/javascript" src="/js/script2.js" async></script> <script type="text/javascript" src="/js/script3.js"></script> <p>conten after script</p> </body> </html>

資源加載順序:

我們發現第一個聲明為async的script1和沒有聲明async的script3是和css同步加載的,而第二個聲明為async的腳本即script2會排隊,等待第一個async腳本加載完畢,defer也如此。

資源優先級

當我們網頁上有許多圖片,腳本和樣式資源時,它們的加載順序是怎樣的呢?舉個例子進行測試:

<!DOCTYPE html>
<html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <link rel="stylesheet" href="/css/animateTop.css"> </head> <body> <img src="/images/img1.png"/> <img src="/images/img2.png"/> <img src="/images/img3.png"/> <img src="/images/img4.png"/> <script type="text/javascript" src="/js/script1.js"></script> <script type="text/javascript" src="/js/script2.js"></script> <script type="text/javascript" src="/js/script3.js"></script> <p>conten after script1</p> </body> </html>

加載順序:

 

我們可以看到,樣式和腳本的優先級是比圖片更高的,因為這兩個都具有阻塞性,瀏覽器讓它們盡快下載下來。

第一個圖片資源會和css一起下載,但瀏覽器發現后面還有許多圖片就會優先去下載腳本文件。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM