html解析和渲染過程 與 Script標簽和腳本執行順序


 

幾個首要特性:

  • script標簽(不帶deferasync屬性)的會阻止文檔渲染。相關腳本會立即下載並執行。
  • document.currentScript可以獲得當前正在運行的腳本(Chrome 29+, FF4+)
  • 腳本順序再默認情況下和script標簽出現的順序一致

 

deferasync屬性(deferasync沒有完全兼容所有瀏覽器

  • 僅有async屬性,腳本會異步執行
  • 僅有defer屬性,腳本會在文檔解析完畢后執行
  • 兩個屬性都沒有,腳本會被同步下載並執行(順序下載,順序執行),期間會阻塞文檔解析

 

如下示例A1,A2,A3

<!-- HTML code -->
<script  src="https://snipt.net/raw/A1_7b08744009c450e07c0bfc1d606fc72e/"></script>
<script  src="https://snipt.net/raw/A2_a2e8c05c1f6fc0e47d259aa899304e89/"></script>
<script  src="https://snipt.net/raw/A3_4fab3017d3d46cbfc4bbd88aab006650/"></script>

當第二個文件A2的尺寸遠大於另外兩個文件,A1下載執行不受影響,A3在A2下載執行完成之后下載

另外,當<script>標簽下載執行過程中,document.ready事件等待所有<script>內容下載完成后才能被觸發

 

優化方案

一:異步加載腳本

setTimeout(function(){
    var s = document.createElement('script');
    s.src = "/will-not-stop-loading.js";
    document.body.appendChild(s);
});

setTimeout未指定第二個參數(延遲時間),會立即執行第一個參數傳入的函數。 但是JavaScript引擎會將該函數插入到執行隊列的末尾。 這意味着正在進行的DOM渲染過程完全結束后(此時瀏覽器忙提示當然會消失),才會調用上述函數

二:load事件(推薦)

$(window).load(function(){
    $('script[type="text/async-script"]').each(function(idx, el){
        var $script = $('<script>');
        if(el.dataset.src) $script.attr('src', el.dataset.src);
        else $script.html(el.text);
        $script.appendTo('body');
        el.remove();
    });
});
  • 對於外部<script>,生成一個新的包含正確src<script>
  • 對於行內<script>,生成一個新的包含正確內容的<script>type默認即為"application/javascript"

  該方法采用DOM中<script>加載的方式,沒有AJAX+Eval改變腳本中當前路徑的缺點。 http://harttleland.com中的Google Analytics、MathJax等腳本都采用這種處理方式

 另外一種寫法

<script type="text/javascript">
// 加載較慢會阻塞頁面渲染的腳本
        function loadComplete(){
            var hm1 = document.createElement("script");
            hm1.src = "./secondLoad.js";
            var hm2 = document.createElement("script");
            hm2.src = "./thirdLoad.js";
            document.body.appendChild(hm1)
            hm1.onload = function(){
                document.body.appendChild(hm2)
            }
        }
    </script>

    <!-- 加載最快且優先級最高的腳本 -->
    <script type=text/javascript onload='loadComplete()' src='./firstAndFastLoad.js'></script>

 

三:document.write()會把輸出寫入到腳本文檔所在的位置,瀏覽器解析完documemt.write()所在文檔內容后,繼續解析document.write()輸出的內容,
然后在繼續解析HTML文檔 

<script type="text/javascript">//<![CDATA[    
  document.write('<script type="text/javascript" src="test.js"><//script>');
  document.write('<script type="text/javascript">');    
  document.write('alert(2);')    
  document.write('alert("我是" + tmpStr);');    
  document.write('<//script>');    //]]>
</script> 

 

 

 

  

 


免責聲明!

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



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