網頁渲染過程(圖解)

從前端的角度,梳理一下,一團代碼是如何渲染到網頁上的

渲染機制


  • <!DOCTYPE> 聲明位於文檔中的最前面,處於 <html> 標籤之前。告知瀏覽器的解析器, 用什麼文檔類型 規範來解析這個文檔
  • 嚴格模式的排版和 JS 運作模式是 以該瀏覽器支持的最高標準運行
  • 在混雜模式中,頁面以寬鬆的向後兼容的方式顯示。模擬老式瀏覽器的行爲以防止站點無法工作。 DOCTYPE不存在或格式不正確會導致文檔以混雜模式呈現

DOM相當於文檔對象模型

一般情況下導致了reflow都會導致repaint

如果避免最小程度的repaint?

一次性的向頁面中插入節點,不要做一次啊操作從新一次

js運行機制

js是單線程的,大白話來理解就是js在同一時間只能做一件事。

任務隊列:
同步任務,異步任務。settimeout setInterval 異步任務。console.log -->同步任務。
js任務隊列是有優先級的,同步任務優先於異步任務。先處理完同步,再處理異步。
eg:

<script type="text/javascript">
            console.log(1);
            setTimeout(function(){
                console.log(2);
            },0);
            console.log(3);
</script>

輸出:


                       console.log('A');
            while(true){}
            console.log('B');

輸出結果:


打印了A之後,會在while(true){} 那裏一直無限循環 進入不了下一步

                        console.log('A);
            setTimeout(function(){
                console.log('B');
            },0)
            while(true){}

這個輸出結果跟上面相同。

上面這2個例子是說明 同步任務和異步任務的優先順序

這個例子是爲了說明 異步任務的放入時間和執行時間



輸出


我用大白話來解釋一下這個原理:for語句是一個同步的任務,當執行i=0的時候,遇到了延時(setTimeout) 延時 等定時器時間到了 纔會把它放在異步任務隊列中,然後等待同步執行完,再執行異步。


JS單線程 我再囉嗦一遍 一個時間之內 JS只能幹一件事情

任務隊列 如上

運行棧裏面放的是同步任務 異步任務是沒法放在裏面的 讓瀏覽器識別到settimeout或者setinterval這些異步任務的時候,是不會把它放在運行棧裏面的,如果有延時,就等到延時時間到了,把它放入任務隊列中。特別注意一點settimeout中的0,一般是4ms,小於4ms的都會按照4ms,這是瀏覽器的規定。

如果任務棧空了,就會去執行異步任務中的任務隊列。

dom事件中的點擊什麼的事件的 等等。

總結:


頁面性能類

cdn很重要
cdn加速

cdn加速是實現加速訪問速度。特點是有助於減輕源站壓力,提高訪問速度,隱藏源服務器等。

DNS預解析:
<meta http-equiv="x-dns=prefetch-control" content="on">這句話的意思:
頁面中a標籤在高級瀏覽器中默認 打開了dns預解析。可以就這句話也不錯。
但是在http4協議開頭 都是默認關閉

這篇博客講解的比較詳細:https://blog.csdn.net/guoqingcun/article/details/52142076

異步加載

動態腳本加載,就是用documentcrateelement一個scrip標籤,已經就是用js創建這麼個標籤,然後把它加在head或者body裏面都可以。就是動態創建節點嘛
defer和async怎麼用呢?就是在加載的scrip的標籤上,加上這2個屬性 就可以了。
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>性能優化</title>
        <script src="./deferl.js" charset="UTF-8" defer="defer"></script>
        <script src="defer2.js"  charset="UTF-8" defer="defer"></script>
    </head>
    <body>
        <div class="">
            test
            <script type="text/javascript">
                console.log('write');
                document.write('<span>write</span>')
            </script>
            <script type="text/javascript">
                for(var i=0;i<20000;i++){
                    if(i%2000===0){
                        console.log(i);
                    }
                }
            </script>
        </div>
    </body>
</html>

輸出:


<script src="./async1.js" charset="UTF-8" async></script>
        <script src="./async2.js"  charset="UTF-8" async></script>

1 和 2的順序 不一定

瀏覽器緩存

強緩存是指 強制緩存,問都不問,就直接緩存。

協商緩存,和服務器協商這個文件能不能用。就是瀏覽器發現本地有這個副本,但是不確定用不用它,就去跟服務器進行協商,問一下,我這個文件要不要用。

接下來將HTTP協議的頭,我請求一個文件的時候,http的響應頭上會攜帶1個或2個東西(這個數量主要看服務器的配置).一個是expires(過期時間),

zhe
這裏相當一個key value,這裏的value值表示的是絕對時間,所以這個時間一般是由服務器下發的,服務器的絕對時間。客服端的時間有可能跟服務器的不一樣,這也就是爲什麼新增加了一個:cache-control。
cache-control是相對時間,相對於客戶端時間,只要在3600s之內,都不會再去服務器拿,直接在瀏覽器本地拿緩存。
如果2者都有,以後者爲準。

接下來說說協商緩存 。

與協商緩存相關的有這四個,一個是last-modified:上次修改的時間,當強緩存失效,過期了,請求的時候會以“if-modified-since”這個字段,並且攜帶這個字段的時間

去給服務器。
Etag是hash值,就是出現這麼個情況,假如只是強緩存的時間過期了,但是內容沒變,這個時候就用到了etag,可以進行match。

這個回答說的很準確。https://zhuanlan.zhihu.com/p/33232074

錯誤監控

notice:window.onerror只能捕獲及時運行錯誤

資源加載錯誤 不會冒泡 object.onerror,不會觸發到window.onerror上。

performance.getEntries()這個方法用於間接獲得資源加載錯誤。
在這裏舉一個例子:



這次都是成功加載 的資源。
比如我們判斷哪個圖片沒有加載成功,先取到所有的標籤節點



然後再相減,就可以得到哪些沒有加載成功。

Error事件捕獲,是在捕獲階段拿到錯誤。
下面演示:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>錯誤捕獲</title>
        <script type="text/javascript">
            window.addEventListener('error',function(e){
                console.log('捕獲',e);
            },true);
        </script>
    </head>
    <body>
        <script src="/baidu.com/test.js" charset="UTF-8"></script>
    </body>
</html>

頁面:


如果不是true,即不是捕獲,就不能找到Error

1.在script標籤增加crossorigin屬性。這個是在客戶端做的。
2.設置js資源響應頭Access-Control-Allow-Origin:* 這個是在服務器端做的。在http頭上加一個Access-Control-Allow-Origin:* 這後面可以是* 也可以是域名 總之要加這兩方面的處理,就可以拿到信息了。

可以用ajax通信的方式上報,但是一般都不會用這個方式上報。

如何利用image對象上報:

<script type="text/javascript">
            (new Image()).src='http://baidu.com/tesk?r=tksjk'
            //src裏面就是錯誤的地址
        </script>

這種方法比ajax方便很多。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章