日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

浏览器渲染机制

發布時間:2023/12/31 HTML 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浏览器渲染机制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、頁面渲染的完整流程

1、頁面渲染的完整流程

瀏覽器從用戶輸入網址之后到底做了什么呢?而從輸入到呈現可以分為兩個部分:網絡通信頁面渲染

網絡通信

一個DNS域名解析的視頻地址:http://vd3.bdstatic.com/mda-iihdr04swzhj4wiy/mda-iihdr04swzhj4wiy.mp4?playlist=%5B%22hd%22%2C%22sc%22%5D

  • 1)用戶輸入url并敲擊回車。

  • 2)域名解析階段: 如果用戶輸入的是ip地址則直接進入第三條。DNS解析的時候,瀏覽器會首先搜索瀏覽器自身的DNS緩存。如果有那么直接使用,如果沒有那么就向本地配置的首選DNS服務器發送域名解析請求,(方式:通過UDP發送請求到53端口)。

    首選DNS服務器【運營商服務器】會先查詢自己的DNS緩沖,如果找到就直接返回,否則代替我們瀏覽器發送迭代請求,首先會去找根域名服務器,(請問www.xxxx.com這個域名的IP地址是多少啊?)因為根域名服務器值存儲了13個根域的DNS的IP地址。所以它只知道頂級域名com的服務器地址,就告訴運營商的DNS我不知道這個域名的IP地址,但是我知道com域的IP地址,你去找它去。

    運營商DNS服務器就去找com頂級域名服務器,(請問www.xxxx.com這個域名的IP地址是多少?)頂級域名服務器,告訴它說,我不知道這個的IP但是我知道xxxx.com的域名服務器地址,你可以去找他。

    運營商DNS服務器就去找xxxx.com二級域名服務器,(請問www.xxxx.com這個域名的IP地址是多少?),它查了一下,找到了,于是告訴了www.xxxx.com的IP地址給了運營商域名服務器,候運營商的DNS服務器就拿到了www.xxxx.com這個域名對應的IP地址,并返回給Windows系統內核,內核又把結果返回給瀏覽器,終于瀏覽器拿到了www.xxxx.com對應的IP地,這次dns解析圓滿成功。

  • 3)TCP發起三次握手階段

    向服務器的WEB程序80端口發起TCP的連接請求,要經過三次握手才能建立成功。

第一步:A向B發送請求報文,同步位SYN=1(表示需要返回響應),seq = x,x為要傳輸數據時候的第一個數據字節的序號第二步:B收到后,如果同意則發送確認信號,同步位SYN=1,ACK = 1(表示該報文是確認報文),自己的序號seq = y,確認序號ack = x + 1;第三步:A收到后回發送確認,這時候沒有了SYN表示不需要回復,ACK = 1表示該條是確認報文,seq = x + 1表示要傳輸的字節序號,同時ack確認號為y + 1;此時A 的 TCP 通知上層應用進程,連接已經建立。 B 的 TCP 收到主機 A 的確認后,也通知其上層 應用進程:TCP 連接已經建立。 復制代碼客戶端: 喂能聽到我說話嗎? 服務器: 能,你能聽到我說話嗎? 客戶端: 很清楚呢,那我們開始聊聊吧。 復制代碼
  • 建立TCP連接后發起http請求
  • 服務器端響應http請求,瀏覽器得到html代碼.

以上是網絡通信部分,接下來將會對頁面渲染部分進行敘述。當瀏覽器拿到html后是如何進行頁面渲染的

頁面渲染

  • 1)HTML文檔解析,構建DOM樹。DOM樹的構建是一個深度遍歷的過程,當前節點的所有子節 點都構建完成以后,才會去構建當前節點的下一個兄弟節點。

  • 2)將CSS解析成CSSOM樹(CSS Rule Tree)。遇到css樣式如link標簽或者style標簽時開始解析css,構建樣式樹。HTML解析 構建和CSS的解析是相互獨立的并不會造成沖突,因此我們通常將css樣式放在head中, 讓瀏覽器盡早解析css;

  • 3)當html的解析遇到script標簽會怎樣呢? 答案是停止DOM樹的解析開始下載js。因為js是會阻塞html解析的,是阻塞資源。其原因在于js可能會改變html現有結構。例如有的節點是用js動態構建的,在這種情況下就會停止dom樹的構建開始下載解析js。

    腳本在文檔的何處插入,就在何處執行。當 HTML 解析器遇到一個 script 標記時,它會暫停構建 DOM,將控制權移交給 JavaScript 引擎;等 JavaScript 引擎運行完畢,瀏覽器會從中斷的地方恢復 DOM 構建。

    而因此就會推遲頁面首繪的時間。可以在首繪不需要js的情況下用async和defer實現異步加載。這樣js就不會阻塞html的解析了。

  • 4)根據DOM樹和CSSOM樹,來構建Render Tree(渲染樹),注意渲染樹,并不等于DOM樹,因為一些像head或display:none的東西,就沒有必要放在渲染樹中了。

  • 5)有了Render Tree,瀏覽器已經能知道網頁中有哪些節點,各個節點的CSS定義,以及它們的從屬關系,下一步操作就是Layout,顧名思義,就是計算出每個節點在屏幕中的位置。布局使用流模型的Layout算法。Layout是一個遞歸的過程,每個節點都負責自己及其子節點的Layout。Layout結果是相對父節點的坐標和尺寸。其過程可以簡述為:
父節點確定自己的寬度 父節點完成子節點放置,確定其相對坐標 節點確定自己的寬度和高度 父節點根據所有的子節點高度計算自己的高度 復制代碼
  • 6)Layout后,瀏覽器已經知道哪些節點要顯示,每個節點的CSS屬性是什么,每個節點在屏幕中的位置是哪里,就進入了最后一步painting,按照算出來的規則,通過顯卡,把內容畫到屏幕上。

2、HTML解析

DOM樹的構建過程為:將字節轉換成字符,確定tokens標記,將tokens轉換成節點,然后構建 DOM 樹。

3、CSS解析

CSSOM的創建過程: 字節 => 字符 => TOken => Node => CSSOM;

在這一過程中,瀏覽器會確定下每一個節點的樣式到底是什么,并且這一過程其實是很消耗資源的。因為樣式你可以自行設置給某個節點,也可以通過繼承獲得。在這一過程中,瀏覽器得遞歸 CSSOM 樹,然后確定具體的元素到底是什么樣式。

注意:CSS匹配HTML元素是一個相當復雜和有性能問題的事情。所以,DOM樹要小,CSS盡量用id和class,千萬不要過渡層疊下去。

css樣式的優先級同樣是件麻煩的事情。

!important > 內聯樣式 > 內部樣式表{ID選擇器>Class選擇器>標簽選擇器} > 外部樣式表 復制代碼

3、渲染樹

樣式樹和DOM樹連接在一起形成一個渲染樹,渲染樹用來計算可見元素的布局并且作為將像素渲染到屏幕上的過程

渲染樹布局

布局階段會從渲染樹的根節點開始遍歷,然后確定每個節點對象在頁面上的確切大小與位置,布局階段的輸出是一個盒子模型,它會精確地捕獲每個元素在屏幕內的確切位置與大小。

渲染樹繪制

在繪制階段,遍歷渲染樹,調用渲染器的paint()方法在屏幕上顯示其內容。渲染樹的繪制工作是由瀏覽器的UI后端組件完成的。

以上我們詳細介紹了瀏覽器工作流程中的重要步驟,接下來我們討論幾個相關的問題:

二、渲染過程中遇到JS文件怎么處理?

JavaScript的加載、解析與執行會阻塞DOM的構建,也就是說,在構建DOM時,HTML解析器若遇到了JavaScript,那么它會暫停構建DOM,將控制權移交給JavaScript引擎,等JavaScript引擎運行完畢,瀏覽器再從中斷的地方恢復DOM構建。

也就是說,如果你想首屏渲染的越快,就越不應該在首屏就加載 JS 文件,這也是都建議將 script 標簽放在 body 標簽底部的原因。當然在當下,并不是說 script 標簽必須放在底部,因為你可以給 script 標簽添加 defer 或者 async 屬性(下文會介紹這兩者的區別)。

JS文件不只是阻塞DOM的構建,它會導致CSSOM也阻塞DOM的構建。

原本DOM和CSSOM的構建是互不影響,井水不犯河水,但是一旦引入了JavaScript,CSSOM也開始阻塞DOM的構建,只有CSSOM構建完畢后,DOM再恢復DOM構建。

這是什么情況?

這是因為JavaScript不只是可以改DOM,它還可以更改樣式,也就是它可以更改CSSOM。前面我們介紹,不完整的CSSOM是無法使用的,但JavaScript中想訪問CSSOM并更改它,那么在執行JavaScript時,必須要能拿到完整的CSSOM。所以就導致了一個現象,如果瀏覽器尚未完成CSSOM的下載和構建,而我們卻想在此時運行腳本,那么瀏覽器將延遲腳本執行和DOM構建,直至其完成CSSOM的下載和構建。也就是說,在這種情況下,瀏覽器會先下載和構建CSSOM,然后再執行JavaScript,最后在繼續構建DOM。

三、你真的了解回流和重繪嗎

我們知道,當網頁生成的時候,至少會渲染一次。在用戶訪問的過程中,還會不斷重新渲染。重新渲染會重復上圖中的第四步(回流)+第五步(重繪)或者只有第五個步(重繪)。

重繪:當render tree中的一些元素需要更新屬性,而這些屬性只是影響元素的外觀、風格,而不會影響布局的,比如background-color。 回流:當render tree中的一部分(或全部)因為元素的規模尺寸、布局、隱藏等改變而需要重新構建 回流必定會發生重繪,重繪不一定會引發回流。重繪和回流會在我們設置節點樣式時頻繁出現,同時也會很大程度上影響性能。回流所需的成本比重繪高的多,改變父節點里的子節點很可能會導致父節點的一系列回流。

1)常見引起回流屬性和方法

添加或者刪除可見的DOM元素; 元素尺寸改變——邊距、填充、邊框、寬度和高度 內容變化,比如用戶在input框中輸入文字 瀏覽器窗口尺寸改變——resize事件發生時 計算 offsetWidth 和 offsetHeight 屬性 設置 style 屬性的值 復制代碼

2)常見引起重繪屬性和方法

栗子:

3)如何減少回流、重繪

1、使用transform 代替 top等 2、盡量少使用table布局,因為可能一點點的改動就會導致重繪制 3、動畫實現的速度的選擇,動畫速度越快,回流次數越多,也可以選擇使用 requestAnimationFrame 4、CSS 選擇符從右往左匹配查找,避免節點層級過多 5、使用 visibility 替換 display: none ,因為前者只會引起重繪,后者會引發回流(改變了布局) 6、 復制代碼

四、async和defer的作用是什么?有什么區別?

  • 沒有 defer 或 async,瀏覽器會立即加載并執行指定的腳本,“立即”指的是在渲染該 script 標簽之下的文檔元素之前,也就是說不等待后續載入的文檔元素,讀到就加載并執行。

  • 有 async,加載和渲染后續文檔元素的過程將和 script.js 的加載與執行并行進行(異步)。

  • 有 defer,加載后續文檔元素的過程將和 script.js 的加載并行進行(異步),但 script.js 的執行要在所有元素解析完成之后,DOMContentLoaded 事件觸發之前完成。

五、為什么操作 DOM 慢

因為 DOM 是屬于渲染引擎中的東西,而 JS 又是 JS 引擎中的東西。當我們通過 JS 操作 DOM 的時候,其實這個操作涉及到了兩個線程之間的通信,那么勢必會帶來一些性能上的損耗。操作 DOM 次數一多,也就等同于一直在進行線程之間的通信,并且操作 DOM 可能還會帶來重繪回流的情況,所以也就導致了性能上的問題。

六、渲染頁面時常見哪些不良現象?

FOUC:由于瀏覽器渲染機制(比如firefox),再CSS加載之前,先呈現了HTML,就會導致展示出無樣式內容,然后樣式突然呈現的現象;

白屏:有些瀏覽器渲染機制(比如chrome)要先構建DOM樹和CSSOM樹,構建完成后再進行渲染,如果CSS部分放在HTML尾部,由于CSS未加載完成,瀏覽器遲遲未渲染,從而導致白屏;也可能是把js文件放在頭部,腳本會阻塞后面內容的呈現,腳本會阻塞其后組件的下載,出現白屏問題。

七、頁面優化方案

  • 1、減少資源請求的次數和壓縮數據內容。因為資源的請求是一個復雜的過程。網速相同的條件下,下載一個100KB的圖片比下載兩個50KB的圖片要快。所以,請減少HTTP請求。

①進行資源打包,如利用webpbck對引入的多個文件進行打包,減少請求次數。 ②使用雪碧圖,可以避免因不同圖片引起的多次資源下載

  • 2、高效合理的css選擇符可以減輕瀏覽器的解析負擔。因為css是逆向解析的所以應當避免多層嵌套。
避免使用通配規則。如 *{} 計算次數驚人!只對需要用到的元素進行選擇 盡量少的去對標簽進行選擇,而是用class。如:#nav li{},可以為li加上nav_item的類名,如下選擇.nav_item{} 不要去用標簽限定ID或者類選擇符。如:ul#nav,應該簡化為#nav 盡量少的去使用后代選擇器,降低選擇器的權重值。后代選擇器的開銷是最高的,盡量將選擇器的深度降到最低,最高不要超過三層,更多的使用類來關聯每一個標簽元素。 考慮繼承。了解哪些屬性是可以通過繼承而來的,然后避免對這些屬性重復指定規則 復制代碼
  • 3、從js層面談頁面優化
①解決渲染阻塞 如果在解析HTML標記時,瀏覽器遇到了JavaScript,解析會停止。只有在該腳本執行完畢后,HTML渲染才會繼續進行。所以這阻塞了頁面的渲染。 解決方法:在標簽中使用 async或defer特性 ②減少對DOM的操作 對DOM操作的代價是高昂的,這在網頁應用中的通常是一個性能瓶頸。 解決辦法:修改和訪問DOM元素會造成頁面的Repaint和Reflow,循環對DOM操作更是罪惡的行為。所以請合理的使用JavaScript變量儲存內容,考慮大量DOM元素中循環的性能開銷,在循環結束時一次性寫入。 減少對DOM元素的查詢和修改,查詢時可將其賦值給局部變量。 ③使用JSON格式來進行數據交換 JSON是一種輕量級的數據交換格式,采用完全獨立于語言的文本格式,是理想的數據交換格式。同時,JSON是 JavaScript原生格式,這意味著在 JavaScript 中處理 JSON數據不需要任何特殊的 API 或工具包。 ④讓需要經常改動的節點脫離文檔流 因為重繪有時確實不可避免,所以只能盡可能限制重繪的影響范圍。 復制代碼
  • 4、使用CDN加速(內容分發網絡)

其基本思路是盡可能避開互聯網上有可能影響數據傳輸速度和穩定性的瓶頸和環節,使內容傳輸的更快、更穩定。通過在網絡各處放置節點服務器所構成的在現有的互聯網基礎之上的一層智能虛擬網絡,CDN系統能夠實時地根據網絡流量和各節點的連接、負載狀況以及到用戶的距離和響應時間等綜合信息將用戶的請求重新導向離用戶最近的服務節點上。

  • 5、 精簡CSS和JS文件

如使用 YUI Compressor壓縮工具,它的特點是:移除注釋;移除額外的空格;細微優化;標識符替換。

八、Load 和 DOMContentLoad

Load 事件觸發代表頁面中的 DOM,CSS,JS,圖片已經全部加載完畢。

DOMContentLoaded 事件觸發代表初始的 HTML 被完全加載和解析,不需要等待 CSS,JS,圖片加載。

深入淺出瀏覽器渲染原理

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的浏览器渲染机制的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。