咱們看幾張的經典流程圖html
咱們一直都在說Javascript是單線程,但瀏覽器是多線程的,在內核控制下互相配合以保持同步,主要的常駐線程有:web
負責渲染界面,解析HTML,CSS,構建DOM和Render樹佈局繪製等。若是過程當中遇到Javascript引擎執行會被掛起線程,GUI更新保存在一個隊列中等待Javascript引擎空閒才執行;瀏覽器
負責解析運行Javascript;執行時間過程會致使頁面渲染加載阻塞;緩存
瀏覽器用以控制事件循環。當Javascript引擎執行過程當中觸發的事件(如點擊,請求等)會將對應任務添加到事件線程中,而當對應的事件符合觸發條件被觸發時會把對應任務添加處處理隊列的尾部等到Javascript引擎空閒時處理;性能優化
由於Javascript引擎是單線程容易阻塞,因此須要有單獨線程爲setTimeout和setInterval計時並觸發,一樣是符合觸發條件(記時完畢)被觸發時會把對應任務添加處處理隊列的尾部等到Javascript引擎空閒時處理;W3C標準規定時間間隔低於4ms被算爲4ms。網絡
XMLHttpRequest在鏈接後瀏覽器新開線程去請求,檢測到狀態變化若是有設置回調函數會產生狀態變動事件,而後把對應任務添加處處理隊列的尾部等到Javascript引擎空閒時處理;多線程
經過 GPU 執行,真正將頁面繪製並輸出到屏幕上app
渲染流程主要步驟:異步
整個過程是一個深度遍歷的操做,它會從當前節點從上往下逐個構建完以後纔會去構建同層級節點及其子節點,最後的結構我網上隨便找了一張圖,大概以下.ide
可是這個過程是能夠被CSS或者Javascript加載而阻塞,這是瀏覽器的一個處理機制,由於這二者均可能會改變DOM樹結構的變化,因此會等它們執行完以後再繼續解析
這裏是跟DOM樹同時生成的,這裏包含了link, style和內聯多份不一樣的樣式整合解析成一份最終的規則,整個結構也是相似DOM樹的屬性結構,最後的結構我也是網上隨便找了一張圖,大概以下.
樣式的整合計算是個很複雜的過程,存在默認樣式,權重,繼承,僞元素,重複定義,單位換算等多種不一樣程度的難題
權重規則大概以下:
實際上瀏覽器 CSS 選擇器的解析規則是從右往左的,每一步都能過濾掉些不符合規則的分支狀況, 直到找到根元素或知足條件的匹配規則的選擇器就結束這個分支的遍歷.因此儘可能避免深層嵌套 CSS, 由於尋找選擇器和計算最終樣式都會受影響的.
DOM樹和CSSOM樹是根據代碼解析而成的,而代碼最終給到瀏覽器渲染的確定是視覺上的表現結構,由於它們都帶有字體,顏色,尺寸,位置甚至是否存在的樣式控制,最後的結構我也是網上隨便找了一張圖,大概以下.
總的來講,會遍歷整個DOM樹節點,忽略不可見節點(例如 meta,header 以及指定了屬性 display: none等節點),得出各個節點的CSS定義以及他們的從屬關係,從而去計算出每一個節點在屏幕中的位置
頁面佈局以可見區域爲畫布,從左到右從上往下從根節點開始佈局.遍歷Render樹調用渲染器的API繪製節點內容填充屏幕進行像素級信息計算與繪製
實際上這一步繪製是在多個層上進行繪製
實際上在paint
以後,display
以前還有一個環節叫渲染層合併
對頁面中 DOM 元素的繪製是在多個層上進行的。在每一個層上完成繪製過程以後,瀏覽器會將全部層按照合理的順序合併成一個圖層,而後顯示在屏幕上。對於有位置重疊的元素的頁面,這個過程尤爲重要,由於一旦圖層的合併順序出錯,將會致使元素顯示異常。(下面會詳解)
這通常是解析過程或者中間樣式結構被改變須要從新進行計算佈局纔會發生,
迴流:當瀏覽器發現變化影響了佈局須要從新計算
重繪:隻影響當前元素的視覺效果而不會影響其餘元素
迴流是影響頁面性能的重要因素之一,儘可能避免
這不是一個按部就班的過程,瀏覽器爲了儘快渲染界面展現給用戶看,從網絡請求獲取到文檔內容的同時就開始局部渲染,而不會等全部HTML解析完纔會建立渲染.並且這是基本的流程,實際上如今主流瀏覽器會有些區別,也會優化整個渲染流程,因此這個過程實際上並無咱們想象中的這麼慢
咱們就以Chrome
爲例
在 Chrome 中其實有幾種不一樣的層類型:
DOM樹每一個節點都有一個對應的渲染對象(RenderObject)
,當它們處於一個相同的座標空間(z軸)就會共同造成一個渲染層.,從上面知道以座標空間區分不一樣的渲染層,因此
而可以知足條件的狀況有:
如下任意屬性值不爲 none 的元素:
摘抄自層疊上下文
DOM節點和渲染對象是一一對應的,知足上面條件的渲染對象擁有獨立的渲染層,不知足的將與其第一個擁有渲染層的父元素共用同一個.簡單來講,RenderObject決定渲染內容,而RenderLayers決定繪製順序.
每一個 GraphicsLayer
對應着一個渲染層是負責最終呈現的內容圖形層,它擁有一個圖形上下文(GraphicsContext)
負責輸出該層的位圖.儲存在共享內存的位圖將做爲紋理上傳到GPU,最後由GPU將多個位圖進行合成繪製.每一個GraphicsLayer能夠獨立的進行渲染而不會相互影響,那麼將一些頻繁重繪的元素放到單獨的GraphicsLayer中就不會對整個頁面形成影響
因此 GraphicsLayer 是一個重要的渲染載體和工具,但它並不直接處理渲染層,而是處理合成層。
某些特殊的渲染層會被提高至合成層(Compositing Layers)
,提高的前提是必須爲 SelfPaintingLayer
(能夠認爲就是上面提到的 NormalPaintLayer
).合成層擁有單獨的 GraphicsLayer,而其餘不是合成層的渲染層,則和其第一個擁有 GraphicsLayer 父層共用一個。
當知足如下條件的渲染層會被瀏覽器自動提高爲合成層
重疊或者說部分重疊在一個合成層之上。(下面隱式合成會講到)
overflow:auto
仍是 overflow:scrill
,只要是能 scroll 便可) 的元素同一個合成層重疊,則其可視子元素也同該合成層重疊好比一個元素的 CSS 動畫效果,動畫運行期間,元素是有可能和其餘元素有重疊的。針對於這種狀況,因而就有了 assumedOverlap 的合成層產生緣由,即便動畫元素視覺上並無和其兄弟元素重疊,但由於 assumedOverlap 的緣由,其兄弟元素依然提高爲了合成層。
須要注意的是該緣由下,有一個很特殊的狀況:
若是合成層有內聯的 transform 屬性,會致使其兄弟渲染層 assume overlap,從而提高爲合成層。
合成層擁有單獨的GraphicsLayers,而其餘渲染層則和第一個擁有GraphicsLayers 的父層共用一個
部分渲染層在一些特定場景下,會被默認提高爲合成層,舉例來講
transform: translateZ(0)
提高至合成層以後,按理說應該會層級更高,可是實際上兩個元素都被提高到合成層,這是由於瀏覽器爲了糾正層疊順序保證視覺效果一致,隱性強行提高了本來高於底層元素層級的元素至合成層一些合成層的條件十分隱蔽,致使產生了不在預期範圍內的合成層,達到必定數量以後會嚴重消耗性能佔用 GPU 和大量的內存資源引發頁面卡頓,造成層爆炸.咱們看下面代碼
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> @keyframes slide { from { transform: none; } to { transform: translateX(100px); } } .animating { width: 300px; height: 30px; background-color: orange; color: #fff; animation: slide 5s alternate linear infinite; } #ul { margin-top: -20px; padding: 5px; border: 1px solid #000; } li { width: 600px; height: 30px; margin-bottom: 5px; background-color: blue; color: #fff; position: relative; /* 會致使沒法壓縮:squashingClippingContainerMismatch */ overflow: hidden; } p { position: absolute; top: 2px; left: 2px; font-size: 16px; line-height: 16px; padding: 2px; margin: 0; background-color: green; } </style> </head> <body> <div class="animating">composited animating</div> <ul id="ul"></ul> </body> <script> window.onload = function() { var $ul = document.getElementById('ul'); for (var i = 0; i < 10; i++) { var ulObj = document.createElement("li"); var pObj = document.createElement("p"); pObj.innerText = i // ulObj.appendChild(pObj); $ul.appendChild(ulObj); } } </script> </html>
實驗可得10個左右已經開始卡頓,100就基本卡死了.再看控制檯如今層的狀況
形成層爆炸的緣由由於知足瞭如下狀況:
assumedOverlap
的緣由,其兄弟元素依然提高爲了合成層。因此li元素都被提高到合成層,若是單單這種狀況仍是能層壓縮的overflow: hidden
,當渲染層同合成層有不一樣的裁剪容器(clipping container)時,該渲染層沒法壓縮(squashingClippingContainerMismatch)最佳方案是打破 overlap 的條件,也就是說讓其餘元素不要和合成層元素重疊。
讓其餘元素不和合成層重疊
.animating { ... position: relative; z-index: 1; }
瀏覽器會對多個渲染層同一個合成層重疊時進行優化,這些渲染層會被壓縮到一個 GraphicsLayer 中,以防止因爲重疊緣由致使可能出現的「層爆炸」,繼續用上面的例子繼續加元素
能夠發如今提高到合成層元素之上的多個不一樣元素會共同提高至同一個合成層,但也有不少沒法壓縮的狀況.但也不是必然,也有不少沒法壓縮的狀況
沒法進行會打破渲染順序的壓縮(squashingWouldBreakPaintOrder)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> #container { position: relative; width: 420px; height: 80px; border: 1px solid black; } #composited { width: 100%; height: 100%; transform: translateZ(0); } #ancestor { -webkit-mask-image: -webkit-linear-gradient(rgba(0, 0, 0, 1), rgba(0, 0, 0, 0)); } #overlap-child { position: absolute; left: 0; top: 10px; bottom: 0px; width: 100%; height: 60px; background-color: orange; } </style> </head> <body> <div id="container"> <div id="composited">Text behind the orange box.</div> <div id="ancestor"> <div id="overlap-child"></div> </div> </div> </body> </html>
在本例中,#overlap-child
同合成層重疊,若是進行壓縮,會致使渲染順序的改變,其父元素 #ancestor
的 mask 屬性將失效,所以相似這種狀況下,是沒法進行層壓縮的。目前常見的產生這種緣由的狀況有兩種,一種是上述的祖先元素使用 mask 屬性的狀況,另外一種是祖先元素使用 filter 屬性的狀況
當渲染層同合成層有不一樣的裁剪容器(clipping container)時,該渲染層沒法壓縮(squashingClippingContainerMismatch)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> .clipping-container { overflow: hidden; height: 10px; background-color: blue; } .composited { transform: translateZ(0); height: 10px; background-color: red; } .target { position: absolute; top: 0px; height: 100px; width: 100px; background-color: green; color: #fff; } </style> </head> <body> <div class="clipping-container"> <div class="composited"></div> </div> <div class="target">不會被壓縮到 composited div 上</div> </body> </html>
本例中 .target
同 合成層 .composited
重疊,可是因爲 .composited
在一個 overflow: hidden
的容器中,致使 .target
和合成層有不一樣的裁剪容器,從而 .target
沒法被壓縮。
相對於合成層滾動的渲染層沒法被壓縮(scrollsWithRespectToSquashingLayer)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> body { height: 1500px; overflow-x: hidden; } .composited { width: 50px; height: 50px; background-color: red; position: absolute; left: 50px; top: 400px; transform: translateZ(0); } .overlap { width: 200px; height: 200px; background-color: green; position: fixed; left: 0px; top: 0px; } </style> </head> <body> <div class="composited"></div> <div class="overlap"></div> </body> </html>
紅色的 .composited
提高爲了合成層,, 當滑動頁面,.overlap
重疊到 .composited
上時,.overlap
會因重疊緣由提高爲合成層,同時,由於相對於合成層滾動,所以沒法被壓縮(原文一開始說只有composited是合成,重疊以後overlap纔會提高,可是我試驗是一開始就都提高了)
再回顧一下流程圖
RenderObject
,裏面包含了關於瀏覽器怎麼渲染節點的信息,若是某些節點不被渲染則不會生成對應的RenderObject
,而RenderObject
的做用就是向GraphicsContext
發出繪製的調用來進行元素的繪製繪製部分摘抄自瞭解瀏覽器渲染的過程和原理
中央處理器(CPU,central processing unit)做爲計算機系統的運算和控制核心,是信息處理、程序運行的最終執行單元。
在計算機體系結構中,CPU 是對計算機的全部硬件資源(如存儲器、輸入輸出單元) 進行控制調配、執行通用運算的核心硬件單元。CPU 是計算機的運算和控制核心。計算機系統中全部軟件層的操做,最終都將經過指令集映射爲CPU的操做。
圖形處理器(英語:Graphics Processing Unit,縮寫:GPU),又稱顯示核心、視覺處理器、顯示芯片,是一種專門在我的電腦、工做站、遊戲機和一些移動設備(如平板電腦、智能手機等)上作圖像和圖形相關運算工做的微處理器。
GPU使顯卡減小了對CPU的依賴,並進行部分本來CPU的工做,尤爲是在3D圖形處理時GPU所採用的核心技術有硬件T&L(幾何轉換和光照處理)、立方環境材質貼圖和頂點混合、紋理壓縮和凹凸映射貼圖、雙重紋理四像素256位渲染引擎等,而硬件T&L技術能夠說是GPU的標誌。
它不僅僅存儲圖形,並且能完成大部分圖形功能,這樣就大大減輕了CPU的負擔,提升了顯示能力和顯示速度。
從上可得,當CPU處理好位圖信息交給GPU渲染可以極大解放CPU負擔,也能快速渲染圖層.固然過分使用會致使嚴重的性能降低,內存佔用太高