瀏覽器渲染阻塞與優化-詳解推遲加載、異步加載。

我認爲一個前端工程師是否優秀,很大程度上取決於對前端性能上優化的功力。因此性能優化對前端真的很重要!!!
本文介紹了什麼是阻塞、爲何會阻塞?阻塞優化經常使用的5種方式以及他們的注意事項。
 
瀏覽器渲染阻塞與優化
      什麼是阻塞?在頁面中咱們一般會引用外部文件,而瀏覽器在解析HTML頁面是從上到下依次解析、渲染,若是<head>中引用了一個a.js文件,而這個文件很大或者有問題,須要2秒加載,那麼瀏覽器會中止渲染頁面(此時是白屏顯示,就是頁面啥都沒有),2秒後加載完成纔會繼續渲染,這個就是阻塞。
     爲何會阻塞?
          由於瀏覽器不知道a.js中執行了哪些腳本,會對頁面形成什麼影響,因此瀏覽器會等js文件下載並執行完成後才繼續渲染,若是這個時間過長,會白屏。
          CSS文件也同樣,由於CSS文件會對DOM的樣式,佈局,色彩,效果產生影響,因此瀏覽器會等CSS文件下載並執行完成後繼續。
          爲了頁面的性能,要避免阻塞。
     
      阻塞優化-推遲加載、異步加載。
           推遲加載(延遲加載)
               若是頁面初始的渲染並不依賴於js或者CSS能夠用推遲加載,就是最後在加載js和css,把引用外部文件的代碼寫在最後。好比一些按鈕的點擊事件,好比輪播圖動畫的腳本也能夠放在最後。
      原理:由於瀏覽器默認是同步加載(這是爲了不重複觸發「迴流」和「重繪」),此時瀏覽器會從上到下逐條代碼的加載、解析、渲染、執行。
複製代碼
 1 <html>
 2      <head>
 3     </head>
 4     <body>
 5         xxxxxxxxxxxxxxx
 6          <h1>推遲加載</h1>
 7          <script type="text/javascript" src="a.js"></script>
 8          <link href="a.css" rel="stylesheet" />
 9      </body>
10 </html>
複製代碼

 

         defer延遲加載:
    在文檔解析完成開始執行,而且在DOMContentLoaded事件以前執行完成,會按照他們在文檔出現的順序去下載解析。效果和把script放在文檔最後</body>以前是同樣的。
          注:defer最好用在 引用 外部文件中使用,用了defer不要使用document.write()方法;使用defer時最好不要請求樣式信息,由於樣式表可能還沒有加載,瀏覽器會禁止該腳本等待樣式表加載完成,至關於樣式表阻塞腳本執行。
 
         異步加載(非阻塞加載)
          注:a.js文件中的代碼以下,這樣就會形成阻塞,由於若是我不點擊肯定,就沒法繼續渲染。
1 alert("已暫停加載")
2 alert("開始加載")
 
            1)async異步加載:就是告訴瀏覽器沒必要等到加載完外部文件,能夠邊渲染邊下載,何時下載完成何時執行。用法就是「async「
1  <script type="text/javascript" src="a.js" async></script>
                注:實際測試中IE10+才支持, 火狐,谷歌,Microsoft支持; 用了async不要使用document.write()方法;使用async時最好不要請求樣式信息,緣由和defer同樣。
      注2:async 在w3school中介紹是IE9就能支持,而IE9也是號稱能支持,可是實際是不能徹底支持的。
 
            2)script dom element法:這個方法是用js動態建立一個script元素添加在document中。
                    : 支持所有瀏覽器(由於IE低版本IE10- 是單線程,因此要修改a.js才能顯示正確的效果)
1 setTimeout("alert('異步加載成功')",2000)     //測試IE時候a.js文件要修改
複製代碼
 1 <script type="text/javascript">
 2     (function() {
 3      var s = document.createElement('script');
 4      s.type = 'text/javascript';
 5      s.async = true;                                        //這句能夠刪除,可是效果不變。
 6      s.src = 'js/a.js';
 7      var x = document.getElementsByTagName('script')[0];
 8      x.parentNode.insertBefore(s, x);
 9  })();
10 </script>
複製代碼
                    注意: 這種方法會阻止onload事件,好比下面的代碼,會等到a.js中的彈出框彈出後再執行。
1 <script type="text/javascript">
2     window.onload=function(){
3         document.getElementById('div').innerHTML="onload完成"
4     }
5 </script>
6 //寫在html中

 

 
             3)onload時異步加載:這個和 script dom element法差很少可是他不是同時執行js和html,他是等html的文件,圖片之類的、頁面全部的資源所有加載完成後再下載執行js,這樣的方法能夠避免阻塞onload事件的觸發。(兼容全部瀏覽器)
複製代碼
 1 (function() {
 2      function async_load(){
 3          var s = document.createElement('script');
 4          s.type = 'text/javascript';
 5          s.async = true;
 6          s.src = 'js/yibujiaz.js';
 7          var x = document.getElementsByTagName('script')[0];
 8          x.parentNode.insertBefore(s, x);
 9      }
10      if (window.attachEvent)
11          window.attachEvent('onload', async_load);
12      else
13          window.addEventListener('load', async_load, false);
14  })();
複製代碼
          注:DOMContentLoaded與onload事件不一樣, DOMContentLoaded是頁面解析完成,頁面的dom元素可使用,可是頁面的圖片、視頻等資源可能還沒加載完成
 
  我上面介紹的優化方式是經常使用的,除此以外還有其餘的,好比異步加載還有AJAX異步加載,body onload異步加載等,這些用的比較少,有興趣的工程師能夠去查查相關資料。(若是你在博客園查基本上只要看一篇文章就行了,其餘的基本上都說同樣的,改都不會改;其實全網都差很少,都說互相轉載複製的)。
 
 a.js所有代碼
1 // setTimeout("alert('異步加載成功')",2000)
2 // alert("已暫停加載")
3 // alert("開始加載")

 

 HTML所有代碼
複製代碼
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>異步加載</title>
    <!-- <script type="text/javascript" src="js/yibujiaz.js" async></script> -->
<script type="text/javascript">
    (function() {
     var s = document.createElement('script');
     s.type = 'text/javascript';
     s.src = 'js/yibujiaz.js';
     var x = document.getElementsByTagName('script')[0];
     x.parentNode.insertBefore(s, x);
 })();
</script>
<!-- <script type="text/javascript">
(function() {
     function async_load(){
         var s = document.createElement('script');
         s.type = 'text/javascript';
         s.async = true;
         s.src = 'js/yibujiaz.js';
         var x = document.getElementsByTagName('script')[0];
         x.parentNode.insertBefore(s, x);
     }
     if (window.attachEvent)
         window.attachEvent('onload', async_load);
     else
         window.addEventListener('load', async_load, false);
 })();
</script>
<script type="text/javascript">
    window.onload=function(){
        document.getElementById('div').innerHTML="onload完成"
    }
</script> -->
    <style type="text/css">
        div{
            width:200px;
            height:200px;
            background-color: blue;
            margin:0 auto;
        }
    </style>
</head>
<body>
    <div id="div">
    </div>
</body>
</html>
複製代碼
相關文章
相關標籤/搜索