<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                >[success] # 瀏覽器頁面加載過程 ~~~ 1.瀏覽器是多線程在加載頁面的時候會用到 'GUI渲染線程'和 'JavaScript 引擎線程' 1.1.'GUI 渲染線程'負責渲染瀏覽器界面 HTML 元素 1.2.'JavaScript 引擎線程'負責處理 JavaScript 腳本程序。 1.3.'HTTP網絡線程,可以開辟N多個:從服務器獲取資源和數據的' 1.4.'DOM監聽線程' .... 2.'js'在執行過程中還可能會改動界面結構和樣式,因此兩個線程是互斥的關系。當 JS 引擎執 行時,GUI 線程會被掛起。 3.html 結構可以看作為三部分組成: 3.1.'<html>'元素是頁面的根元素,它描述完整的網頁; 3.2.'<head>'元素包含了我們想包含在 HTML 頁面中,但不希望顯示在網頁里的內容; 3.3.'<body>'元素包含了我們訪問頁面時所有顯示在頁面上的內容,是用戶最終能看到的內容。 ~~~ ![](https://img.kancloud.cn/4f/20/4f20878b45856ed4d8fc099e97d8ce39_899x423.png) >[info] ## 打開頁面加載過程 ~~~html 1.瀏覽器會從服務器中獲取到 HTML 內容 2.瀏覽器獲取到 HTML 內容后,就開始從上到下解析 HTML 的元素 3.'<head>'元素內容會先被解析,此時瀏覽器還沒開始渲染頁面。當遇到'head' 標簽內部一般會有 3.1.頁面元數據的<meta>元素 3.2.還有一些<link>元素涉及外部資源(如圖片、CSS 樣式等),此時瀏覽器會去獲取這些外部 資源。 3.3.<script>元素通過src屬性指向外部資源。 4.當瀏覽器解析<script>,會暫停解析并下載 JavaScript 腳本。 5.當 JavaScript 腳本下載完成后,瀏覽器的控制權轉交給 JavaScript 引擎。當腳本執行完成后, 控制權會交回給渲染引擎,渲染引擎繼續往下解析 HTML 頁面。 6.<body>元素內容開始被解析,瀏覽器開始渲染頁面。 ~~~ >[danger] ##### DOM 樹 -- 處理 HTML 標記,構建 DOM 樹 ~~~ 1.從服務器基于HTTP網路請求回來的數據先是'16進制的文件流' =>'瀏覽器把它解析為字符串(HTML字符串)' =>'按照W3C規則識別成為一個個的節點「詞法解析」' =>'生成樹' ~~~ ![](https://img.kancloud.cn/42/4c/424cc6311e6b55dde18ef15a9ed14cd9_1164x621.png) >[danger] ##### CSSOM樹 ~~~ 1.在處理HTML時,解析器可能會碰到引用外部樣式表的link元素。 2.然后,使用CSS對象模型規范將此CSS樣式表解析為地圖 。 3.然后可以將生成的代碼應用于DOM中的元素 。 4.CSSOM 依賴DOM 樹 ,既然已經有了DOM樹結構來表示HTML文檔結構,那為什么不把CSS 順便放在在DOM上,以便我們直接從Element上獲取所有樣式信息呢? 很明顯,如果把CSS信息一起建模在DOM結構上,就會違背'單一職責原則'。因為正如在網頁中HTML承擔了 語義職能,CSS承擔了表現職能一樣,在計算機中DOM承擔了語義職能,而CSSOM承擔了表現職能。仔細看 下圖僅僅是對dom 節點的css做了生成樹,這時候并沒有節點中的內容 ~~~ ![](https://img.kancloud.cn/02/47/0247648b35870dd43150a317405467fc_931x402.png) >[danger] ##### Render-Tree渲染樹 1. 當有了**DOM Tree**和 **CSSOM Tree**后,就可以兩個結合來構建**Render Tree**了 2. **link**元素不會阻塞**DOM Tree**的構建過程,但是會阻塞**Render Tree**的構建過程,這是因為Render Tree在構建時,需要對應的CSSOM Tree 3. **Render Tree和DOM Tree**并不是一一對應的關系,比如對于display為none的元素,壓根不會出現在render tree中 ![](https://img.kancloud.cn/9d/77/9d77c4f5604ac846fff5af21618e3f3f_1081x470.png) >[danger] ##### 布局繪制 1. 在渲染樹(Render Tree)上運行布局(Layout)以計算每個節點的幾何體,渲染樹會表示顯示哪些節點以及其他樣式,但是不表示每個節點的**尺寸、位置**等信息,**布局**是確定呈現樹中所有節點的**寬度、高度和位置**信息 ![](https://img.kancloud.cn/14/1e/141e0b779f7720e264d9b7f78ca7d126_1196x538.png) >[danger] ##### 將每個節點繪制(Paint)到屏幕上 1. 在繪制階段,瀏覽器將布局階段計算的每個frame轉為屏幕上實際的像素點; 2. 包括將元素的可見部分進行繪制,比如文本、顏色、邊框、陰影、替換元素(比如img) ![](https://img.kancloud.cn/58/d4/58d4b2155ddf3af2ad3de348e4a1df5e_1108x234.png) >[danger] ##### 放置順序產生問題 ~~~html 1.<head>中放置的<script>元素會阻塞頁面的渲染過程因為上面說過,當 JS 引擎執行時,GUI 線 程會被掛起。因此把 JavaScript 放在<head>里,意味著必須把所有 JavaScript 代碼都下載、解 析和解釋完成后,才能開始渲染頁面。 對應問題:外部腳本加載時間很長(比如一直無法完成下載),就會造成網頁長時間失去響應, 瀏覽器就會呈現“假死”狀態,用戶體驗會變得很糟糕 2.將 JavaScript 腳本放在<body>的最后面。這樣可以避免資源阻塞,頁面得以迅速展示 ~~~ >[danger] ##### 為什么加載script 會阻止dom ~~~ 1. HTML 解析器找到 <script> 標簽后,它將暫停 HTML 文檔的解析,并且 必須加載、解析和執行 JavaScript 代碼。因為 JavaScript 可以使用諸如 document.write() 更改整個 DOM 結構之類的東西來更改文檔的形狀,因此 HTML 解析器必須等待 JavaScript 運行才能恢復HTML文檔解析。 ~~~ >[danger] ##### 總結 ~~~ 1.整個過程如下 DOM TREE(DOMContentLoaded事件觸發) -> 「執行JS」沒完成會阻止接下來的渲染 -> CSSOM TREE -> RENDER TREE渲染樹「瀏覽器未來是按照這個樹來繪制頁面的」-> Layout布局計算「回流/重排」 -> Painting繪制「重繪」{ 分層繪制 } ~~~ ![](https://img.kancloud.cn/c3/ad/c3adeb2cbb0763be0811bccad4e72706_682x358.png) [DOMContentLoaded與load的區別 讀一下](https://www.cnblogs.com/caizhenbo/p/6679478.html) >[info] ## 關于defer/async ~~~ 1.通過下面案例在'script 引入 index.js' 其中'index.js' 是一個從10000打印到0的一個方法,下面 是四種不同形式的使用 '注':當你在你本地想查看同等案例的時候需要一次僅放開一種情況來查看效果 2.運行產生的效果 2.1.第一種情況'sprict'放置頂部,運行后'<p>我在開始渲染</p>' 沒有立刻渲染 2.2.第二種情況'sprict' 增加了'defer'屬性,運行后'<p>我在開始渲染</p>' 立刻渲染 2.3.第三種情況'sprict' 增加了'async'屬性,運行后'<p>我在開始渲染</p>' 立刻渲染 2.4.第四種情況'sprict' 放到底部,運行后'<p>我在開始渲染</p>' 立刻渲染 3.關于第二種和第三種,了解之前需要知道一個概念,sprict 這里需要兩部分來看,第一部分 是'下載',第二部分是'執行',像第一種和第四種他們都是'下載和執行'全部阻礙html渲染,并且瀏覽 器一次只能執行一個文件。 也就是說,異步加載允許瀏覽器同時'下載'多個文件以及執行單個文 件,但不能同時'執行'多個文件,簡單的說'下載'不會阻止其他文件的下載和其他文件的執行,但是 一個文件的'執行'會阻止其他文件的'執行' 但不阻止下載,那么因此實際可以做到優化的位置就 是'下載',讓第一種和第四種出現'下載'和'執行'的問題拆解,因此問題就變得何時觸發執行 ~~~ * 第一種 和 第四種情況圖 ~~~ 1.JS 引擎執行時,GUI 線程會被掛起,所以像下圖展示效果先html 解析,遇到'sprict' 下載 對應資源,下載后解析資源,在重新渲染html,但由于第一種和第四種位置放置區別,產生 了兩種不同效果 ~~~ ![](https://img.kancloud.cn/81/3e/813eafdcbccd1942f5be0380b56d35b2_716x184.png) * html ~~~html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <!-- 第一種 --> <script src="index.js"></script> <!-- 第二種 --> <script defer src="index.js"></script> <!-- 第三種 --> <script async src="index.js"></script> </head> <body> <p>我在開始渲染</p> <!-- 第四種 --> <script src="index.js"></script> </body> </html> ~~~ * index.js ~~~ let count = 10000 while (count) { count -= 1 console.log(count); } ~~~ >[danger] ##### Async -- 異步 ~~~ 1.async 允許在瀏覽器執行其他操作時并行動作去下載指定的 JS 資源,一旦文件的下載完成, 瀏覽器將立即開始執行它。 因此只要文件下載完 JS 文件的執行將阻止網頁/HTML 文件的當前渲 染。'簡單'的說解決下載,讓下載和其他操作可以同步,但當下載完成后的立即執行效果依舊 會阻止'html' 渲染 2.async 腳本執行的順序是不可預測 如圖二,將三個腳本,每個腳本將一個數字記錄到控制臺 中,使用async加載順序將變得不可預測。 3.async不會能保證在DOMContentLoaded之前或者之后執行 ~~~ ![](https://img.kancloud.cn/79/91/799186d005394b15600cb7e97fed8562_599x168.png) * 圖二 ![](https://img.kancloud.cn/90/f0/90f02ad0c73940ee37f87b738dcef078_672x242.png) >[danger] ##### defer-- 延遲 ~~~ 1.defer 屬性的 JS 文件將與其他文件同時下載,僅在 HTML 文件呈現完成后才開始執行下載的資 源,而不是像 async 在資源下載完成后立即執行。 因此,延遲文件的下載和執行都不會阻塞渲 染。 2.defer 加載順序將始終按照指定 3. 它會等待DOM Tree構建完成,在DOMContentLoaded事件之前先執行defer中的代碼 ~~~ ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="./js/test.js" defer></script> <script src="./js/demo.js" defer></script> </head> <body> <div id="app">app</div> <div class="box"></div> <div id="title">title</div> <div id="nav">nav</div> <div id="product">product</div> <!-- 1.下載需要很長的事件, 并且執行也需要很長的時間 --> <!-- 總結一: 加上defer之后, js文件的下載和執行, 不會影響后面的DOM Tree的構建 --> <script> // 總結三: defer代碼是在DOMContentLoaded事件發出之前執行 window.addEventListener("DOMContentLoaded", () => { console.log("DOMContentLoaded") }) </script> <h1>哈哈哈哈啊</h1> </body> </html> ~~~ ![](https://img.kancloud.cn/cf/03/cf03cd6f810ad0ec78e7d83d5279c7a3_644x204.png) ![](https://img.kancloud.cn/44/14/44146f3a3fb934376b3636c073103cc7_659x250.png) >[danger] ##### 總結 ~~~ 1.遇到 <script src='xxx/xxx.js'>,會阻礙GUI的渲染 1.1.defer:和link是類似的機制了,不會阻礙GUI渲染,當GUI渲染完,才會把請求回來的JS去渲染... 1.2.async:請求JS資源是異步的「單獨開辟HTTP去請求」,此時GUI繼續渲染;但是一但當JS請求回來, 會立即暫停GUI的處理,接下來去渲染JS 2.加入我們有5個JS的請求,如果不設置任何屬性,肯定是按照順序請求和渲染JS的「依賴關系是有效的」; 但是如果設置async,誰先請求回來就先渲染誰,依賴關系是無效的;如果使用defer是可以建立依賴關系的 (瀏覽器內部在GUI渲染完成后,等待所有設置defer的資源都請求回來,再按照編寫的依賴順序去加載渲染js); 3.真實項目開發,我們一般把link放在頁面的頭部「是為了在沒有渲染DOM的時候,就通知HTTP去請求CSS了, 這樣DOM渲染玩,CSS也差不多回來了,更有效的利用時間,提高頁面的渲染速度」;我們一般把JS放在頁面 的底部,防止其阻礙GUI的渲染,如果不放在底部,我們最好設置上async/defer...; ~~~ >[danger] ##### 瀏覽器渲染過程 未讀 https://web.dev/howbrowserswork/ >[danger] ##### 關于二者使用場景參考 [How and when to use Async and Defer attributes](https://zellwk.com/blog/javascript-async-and-defer/) >[info] ## 文章來源 [01 | 重識 HTML,掌握頁面基本結構和加載過程2021/04/09 王貝珊(被刪)](https://kaiwu.lagou.com/course/courseInfo.htm?courseId=822#/detail/pc?id=7196) [Async vs Defer vs Preload vs Server Push](https://webspeedtools.com/async-vs-defer-vs-preload-vs-server-push/#Async) [How and when to use Async and Defer attributes](https://zellwk.com/blog/javascript-async-and-defer/) [更快地構建DOM: 使用預解析, async, defer 以及 preload](https://www.w3cplus.com/javascript/building-the-dom-faster-speculative-parsing-async-defer-and-preload.html)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看