整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          你不知道的瀏覽器渲染原理

          你不知道的瀏覽器渲染原理

          瀏覽器的內核是指支持瀏覽器運行的最核心的程序,分為兩個部分的,一是渲染引擎,另一個是 JS 引擎。渲染引擎在不同的瀏覽器中也不是都相同的。目前市面上常見的瀏覽器內核可以分為這四種:Trident(IE)、Gecko(火狐)、Blink(Chrome、Opera)、Webkit(Safari)。這里面大家最耳熟能詳的可能就是 Webkit 內核了,Webkit 內核是當下瀏覽器世界真正的霸主。

          本文我們就以 Webkit 為例,對現代瀏覽器的渲染過程進行一個深度的剖析。

          想閱讀更多優質文章請猛戳GitHub 博客。

          頁面加載過程

          在介紹瀏覽器渲染過程之前,我們簡明扼要介紹下頁面的加載過程,有助于更好理解后續渲染過程。

          要點如下:

          • 瀏覽器根據 DNS 服務器得到域名的 IP 地址;
          • 向這個 IP 的機器發送 HTTP 請求;
          • 服務器收到、處理并返回 HTTP 請求;
          • 瀏覽器得到返回內容。

          例如在瀏覽器輸入https://juejin.im/timeline,然后經過 DNS 解析,juejin.im對應的 IP 是36.248.217.149(不同時間、地點對應的 IP 可能會不同)。然后瀏覽器向該 IP 發送 HTTP 請求。

          服務端接收到 HTTP 請求,然后經過計算(向不同的用戶推送不同的內容),返回 HTTP 請求,返回的內容如下:


          其實就是一堆 HMTL 格式的字符串,因為只有 HTML 格式瀏覽器才能正確解析,這是 W3C 標準的要求。接下來就是瀏覽器的渲染過程。

          瀏覽器渲染過程


          瀏覽器渲染過程大體分為如下三部分:

          1)瀏覽器會解析三個東西:

          一是 HTML/SVG/XHTML,HTML 字符串描述了一個頁面的結構,瀏覽器會把 HTML 結構字符串解析轉換 DOM 樹形結構。


          二是 CSS,解析 CSS 會產生 CSS 規則樹,它和 DOM 結構比較像。


          三是 Javascript 腳本,等到 Javascript 腳本文件加載后, 通過 DOM API 和 CSSOM API 來操作 DOM Tree 和 CSS Rule Tree。


          2)解析完成后,瀏覽器引擎會通過 DOM Tree 和 CSS Rule Tree 來構造 Rendering Tree。

          • Rendering Tree 渲染樹并不等同于 DOM 樹,渲染樹只會包括需要顯示的節點和這些節點的樣式信息。
          • CSS 的 Rule Tree 主要是為了完成匹配并把 CSS Rule 附加上 Rendering Tree 上的每個 Element(也就是每個 Frame)。
          • 然后,計算每個 Frame 的位置,這又叫 layout 和 reflow 過程。

          3)最后通過調用操作系統 Native GUI 的 API 繪制。

          接下來我們針對這其中所經歷的重要步驟詳細闡述

          構建 DOM

          瀏覽器會遵守一套步驟將 HTML 文件轉換為 DOM 樹。宏觀上,可以分為幾個步驟:


          瀏覽器從磁盤或網絡讀取 HTML 的原始字節,并根據文件的指定編碼(例如 UTF-8)將它們轉換成字符串。

          在網絡中傳輸的內容其實都是 0 和 1 這些字節數據。當瀏覽器接收到這些字節數據以后,它會將這些字節數據轉換為字符串,也就是我們寫的代碼。

          將字符串轉換成 Token,例如:<html>、<body>等。Token 中會標識出當前 Token 是“開始標簽”或是“結束標簽”亦或是“文本”等信息

          這時候你一定會有疑問,節點與節點之間的關系如何維護?

          事實上,這就是 Token 要標識“起始標簽”和“結束標簽”等標識的作用。例如“title”Token 的起始標簽和結束標簽之間的節點肯定是屬于“head”的子節點。


          上圖給出了節點之間的關系,例如:“Hello”Token 位于“title”開始標簽與“title”結束標簽之間,表明“Hello”Token 是“title”Token 的子節點。同理“title”Token 是“head”Token 的子節點。

          • 生成節點對象并構建 DOM

          事實上,構建 DOM 的過程中,不是等所有 Token 都轉換完成后再去生成節點對象,而是一邊生成 Token 一邊消耗 Token 來生成節點對象。換句話說,每個 Token 被生成后,會立刻消耗這個 Token 創建出節點對象。注意:帶有結束標簽標識的 Token 不會創建節點對象。

          接下來我們舉個例子,假設有段 HTML 文本:

          復制代碼

          <html>
          <head>
           <title>Web page parsing</title>
          </head>
          <body>
           <div>
           <h1>Web page parsing</h1>
           <p>This is an example Web page.</p>
           </div>
          </body>
          </html>
          

          上面這段 HTML 會解析成這樣:


          構建 CSSOM

          DOM 會捕獲頁面的內容,但瀏覽器還需要知道頁面如何展示,所以需要構建 CSSOM。

          構建 CSSOM 的過程與構建 DOM 的過程非常相似,當瀏覽器接收到一段 CSS,瀏覽器首先要做的是識別出 Token,然后構建節點并生成 CSSOM。


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

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

          構建渲染樹

          當我們生成 DOM 樹和 CSSOM 樹以后,就需要將這兩棵樹組合為渲染樹。


          在這一過程中,不是簡單的將兩者合并就行了。渲染樹只會包括需要顯示的節點和這些節點的樣式信息,如果某個節點是 display: none 的,那么就不會在渲染樹中顯示。

          我們或許有個疑惑:瀏覽器如果渲染過程中遇到 JS 文件怎么處理

          渲染過程中,如果遇到<script>就停止渲染,執行 JS 代碼。因為瀏覽器有 GUI 渲染線程與 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


          布局與繪制

          當瀏覽器生成渲染樹以后,就會根據渲染樹來進行布局(也可以叫做回流)。這一階段瀏覽器要做的事情是要弄清楚各個節點在頁面中的確切位置和大小。通常這一行為也被稱為“自動重排”。

          布局流程的輸出是一個“盒模型”,它會精確地捕獲每個元素在視口內的確切位置和尺寸,所有相對測量值都將轉換為屏幕上的絕對像素。

          布局完成后,瀏覽器會立即發出“Paint Setup”和“Paint”事件,將渲染樹轉換成屏幕上的像素。

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

          幾點補充說明

          1.async 和 defer 的作用是什么?有什么區別?

          接下來我們對比下 defer 和 async 屬性的區別:


          其中藍色線代表 JavaScript 加載;紅色線代表 JavaScript 執行;綠色線代表 HTML 解析。

          1)情況 1<script src="script.js"></script>

          沒有 defer 或 async,瀏覽器會立即加載并執行指定的腳本,也就是說不等待后續載入的文檔元素,讀到就加載并執行。

          2)情況 2<script async src="script.js"></script> (異步下載)

          async 屬性表示異步執行引入的 JavaScript,與 defer 的區別在于,如果已經加載好,就會開始執行——無論此刻是 HTML 解析階段還是 DOMContentLoaded 觸發之后。需要注意的是,這種方式加載的 JavaScript 依然會阻塞 load 事件。換句話說,async-script 可能在 DOMContentLoaded 觸發之前或之后執行,但一定在 load 觸發之前執行。

          3)情況 3 <script defer src="script.js"></script>(延遲執行)

          defer 屬性表示延遲執行引入的 JavaScript,即這段 JavaScript 加載時 HTML 并未停止解析,這兩個過程是并行的。整個 document 解析完畢且 defer-script 也加載完成之后(這兩件事情的順序無關),會執行所有由 defer-script 加載的 JavaScript 代碼,然后觸發 DOMContentLoaded 事件。

          defer 與相比普通 script,有兩點區別:載入 JavaScript 文件時不阻塞 HTML 的解析,執行階段被放到 HTML 標簽解析完成之后。

          在加載多個 JS 腳本的時候,async 是無順序的加載,而 defer 是有順序的加載。

          2. 為什么操作 DOM 慢?

          把 DOM 和 JavaScript 各自想象成一個島嶼,它們之間用收費橋梁連接。——《高性能 JavaScript》

          JS 是很快的,在 JS 中修改 DOM 對象也是很快的。在 JS 的世界里,一切是簡單的、迅速的。但 DOM 操作并非 JS 一個人的獨舞,而是兩個模塊之間的協作。

          因為 DOM 是屬于渲染引擎中的東西,而 JS 又是 JS 引擎中的東西。當我們用 JS 去操作 DOM 時,本質上是 JS 引擎和渲染引擎之間進行了“跨界交流”。這個“跨界交流”的實現并不簡單,它依賴了橋接接口作為“橋梁”(如下圖)。


          過“橋”要收費——這個開銷本身就是不可忽略的。我們每操作一次 DOM(不管是為了修改還是僅僅為了訪問其值),都要過一次“橋”。過“橋”的次數一多,就會產生比較明顯的性能問題。因此“減少 DOM 操作”的建議,并非空穴來風。

          3. 你真的了解回流和重繪嗎?

          渲染的流程基本上是這樣(如下圖黃色的四個步驟):

          1. 計算 CSS 樣式

          2. 構建 Render Tree

          3.Layout – 定位坐標和大小

          4. 正式開畫


          注意:上圖流程中有很多連接線,這表示了 Javascript 動態修改了 DOM 屬性或是 CSS 屬性會導致重新 Layout,但有些改變不會重新 Layout,就是上圖中那些指到天上的箭頭,比如修改后的 CSS rule 沒有被匹配到元素。

          這里重要要說兩個概念,一個是 Reflow,另一個是 Repaint

          重繪:當我們對 DOM 的修改導致了樣式的變化、卻并未影響其幾何屬性(比如修改了顏色或背景色)時,瀏覽器不需重新計算元素的幾何屬性、直接為該元素繪制新的樣式(跳過了上圖所示的回流環節)。

          回流:當我們對 DOM 的修改引發了 DOM 幾何尺寸的變化(比如修改元素的寬、高或隱藏元素等)時,瀏覽器需要重新計算元素的幾何屬性(其他元素的幾何屬性和位置也會因此受到影響),然后再將計算的結果繪制出來,這個過程就是回流(也叫重排)。

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

          回流必定會發生重繪,重繪不一定會引發回流。重繪和回流會在我們設置節點樣式時頻繁出現,同時也會很大程度上影響性能。回流所需的成本比重繪高的多,改變父節點里的子節點很可能會導致父節點的一系列回流。

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

          任何會改變元素幾何信息 (元素的位置和尺寸大小) 的操作,都會觸發回流,

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

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


          3)如何減少回流、重繪

          • 使用 transform 替代 top;
          • 使用 visibility 替換 display: none ,因為前者只會引起重繪,后者會引發回流(改變了布局);
          • 不要把節點的屬性值放在一個循環里當成循環里的變量。

          復制代碼

          for(let i=0; i < 1000; i++) {
           // 獲取 offsetTop 會導致回流,因為需要去獲取正確的值
           console.log(document.querySelector('.test').style.offsetTop)
          }
          
          • 不要使用 table 布局,可能很小的一個小改動會造成整個 table 的重新布局;
          • 動畫實現的速度的選擇,動畫速度越快,回流次數越多,也可以選擇使用 requestAnimationFrame;
          • CSS 選擇符從右往左匹配查找,避免節點層級過多;
          • 將頻繁重繪或者回流的節點設置為圖層,圖層能夠阻止該節點的渲染行為影響別的節點。比如對于 video 標簽來說,瀏覽器會自動將該節點變為圖層。

          性能優化策略

          基于上面介紹的瀏覽器渲染原理,DOM 和 CSSOM 結構構建順序,初始化可以對頁面渲染做些優化,提升頁面性能。

          • JS 優化: <script> 標簽加上 defer 屬性 和 async 屬性 用于在不阻塞頁面文檔解析的前提下,控制腳本的下載和執行。
          • defer 屬性: 用于開啟新的線程下載腳本文件,并使腳本在文檔解析完成后執行。
          • async 屬性: HTML5 新增屬性,用于異步下載腳本文件,下載完畢立即解釋執行代碼。
          • CSS 優化: <link> 標簽的 rel 屬性 中的屬性值設置為 preload 能夠讓你在你的 HTML 頁面中可以指明哪些資源是在頁面加載完成后即刻需要的,最優的配置加載順序,提高渲染性能。

          總結

          綜上所述,我們得出這樣的結論:

          • 瀏覽器工作流程:構建 DOM -> 構建 CSSOM -> 構建渲染樹 -> 布局 -> 繪制。
          • CSSOM 會阻塞渲染,只有當 CSSOM 構建完畢后才會進入下一個階段構建渲染樹。
          • 通常情況下 DOM 和 CSSOM 是并行構建的,但是當瀏覽器遇到一個不帶 defer 或 async 屬性的 script 標簽時,DOM 構建將暫停,如果此時又恰巧瀏覽器尚未完成 CSSOM 的下載和構建,由于 JavaScript 可以修改 CSSOM,所以需要等 CSSOM 構建完畢后再執行 JS,最后才重新 DOM 構建。

          參考文章

          • https://segmentfault.com/q/1010000000640869
          • https://coolshell.cn/articles/9666.html
          • https://juejin.im/book/5bdc715fe51d454e755f75ef/section/5c024ecbf265da616a476638
          • https://mp.weixin.qq.com/s?__biz=MzA5NzkwNDk3MQ==&mid=2650588806&idx=1&sn=408a54e7c8102fd6944c9a40b119015a&chksm=8891d6a2bfe65fb42f493fe9a4dab672dd7e440f31e753196cee0cfbc6696e4f8dd3a669e040&mpshare=1&scene=1&srcid=1228ZrXsmbZKcgCSu7zTVDwy#
          • https://juejin.im/book/5b936540f265da0a9624b04b/section/5bac3a4df265da0aa81c043c
          • https://juejin.im/book/5c47343bf265da612b13e5c0/section/5c4737375188255de8397ae3
          • https://juejin.im/book/5a8f9ddcf265da4e9f6fb959/section/5a8f9f7bf265da4e82635e46

          更多內容,請關注前端之巔。

          、什么是Canvas

          想必學習前端的同學們對Canvas 都不陌生,它是 HTML5 新增的“畫布”元素,可以使用JavaScript來繪制圖形。

          Canvas元素是在HTML5中新增的標簽用于在網頁實時生成圖像,并且可以操作圖像內容,基本上它是一個可以用JavaScript操作的位圖(bitmap)。Canvas 由一個可繪制區域HTML代碼中的屬性定義決定高度和寬度。JavaScript代碼可以訪問該區域,通過一套完整的繪圖功能的API生成動態的圖形。

          二. 引入Canvas的重要性

          HTML5 在 2012 年已形成了穩定的版本,在此之前很長一段時間,開發者們繪制圖形選擇的方案更多是SVG來實現。SVG使用XML來定義圖形,就像使用HTML標簽一樣來控制元素的排布,SVG的本質就是一個DOM元素。當圖形內容太過豐富后,性能和內存上就會大打折扣。一旦涉及頻繁的圖片繪制場景,這個實現對于用戶的體驗將是毀滅性的。

          渲染動畫的基本原理,無非是反復地擦除和重繪。為了動畫的流暢,留給開發者渲染一幀的時間,只有短短的 16.67ms。在這16.67ms中,我不僅需要處理一些繪制邏輯,計算每個對象的位置、狀態,還需要把它們都畫出來。如果消耗的時間稍稍多了一些,用戶就會感受到“卡頓”。所以,在編寫動畫時,開發者們無時無刻不擔憂著動畫的性能,唯恐渲染的耗時過長。

          在現代 Web 開發中,開發者們更多的會借助 Canvas 提供的API去繪制上下文,可以自由繪制各種2D和3D圖形,創建富有視覺沖擊力的游戲場景和角色。Canvas的使用可以使得游戲能夠實現流暢的動態效果和用戶交互。無論是簡單的小游戲還是復雜的游戲引擎,Canvas 都被廣泛應用。

          下面是做的一個簡單的對比試驗,可以很明顯感受到兩者的差距,分別使用SVG和Canvas繪制一個包含著100w個圓形的500*500的圖片,根據耗時計算對比,Canvas耗費的時間幾乎只有SVG的一半:

          三. 計算與渲染

          把動畫的一幀渲染出來,需要經過以下步驟:

          1. 計算:處理網頁渲染邏輯,計算每個對象的狀態和位置。
          2. 渲染:真正把對象繪制出來。
          • JavaScript 調用 DOM API(包括 Canvas API)以進行渲染。
          • 瀏覽器(通常是另一個渲染線程)把渲染后的結果呈現在屏幕上的過程。

          之前提到過,在動畫設計和開發中,每幀只有16.67毫秒的時間用于渲染。這個數值是通過計算每秒60幀得出的平均每幀渲染時間。實際上,并不是所有設備都能夠穩定地達到60FPS。因此,為了確保在不同設備上實現一致性的動畫效果,最好將每幀的渲染時間控制在10毫秒以內。

          大家都知道,通常情況下,渲染的開銷遠大于計算(相差3~4個量級)。除非使用了一些時間復雜度很高的算法,否則不需要過于深入優化計算環節。Canvas的渲染是在JavaScript引擎中執行繪制邏輯,通過構建畫布在內存中,并遍歷所有像素點的顏色,最終輸出到屏幕上。這種強大的功能可能會增加學習成本,但如今仍然有很多開發者選擇和接受Canvas,這要歸功于Canvas最大的優勢:渲染性能的出色表現。

          四. Canvas渲染性能優勢

          當談論圖形渲染技術時,就不得不提到DOM駐留模式和Canvas快速模式。

          DOM駐留模式

          DOM駐留模式是一種基于文檔對象模型(DOM)的渲染技術。在DOM駐留模式下,頁面的布局和樣式是由DOM樹來掌管的。當頁面需要更新時,瀏覽器會重新計算布局和樣式并重新渲染。此模式非常靈活,特別適用于處理動態頁面交互和多樣化的樣式控制。然而,由于需要頻繁地重新計算布局和樣式,對于復雜的圖形渲染任務來說,性能開銷相對較高。

          Canvas快速模式

          Canvas快速模式利用HTML5的Canvas元素進行圖形渲染。在這種模式下,開發者可以使用Canvas提供的2D或3D繪圖API直接在畫布上繪制圖形。相比于DOM駐留模式,Canvas快速模式更加高效。它不關心頁面的布局和樣式,而是在需要時只重繪受影響的部分。這樣就避免了頻繁的布局和樣式計算,提高了渲染性能。

          分層提高Canvas性能

          開發者們通過分析大量實際場景,總結出一套可以進一步提升Canvas性能的策略,即對變化較少和變化較多的內容進行分開渲染。這種策略就是所謂的分層Canvas。它能夠顯著降低完全沒有必要的渲染性能開銷。分層渲染的思想被廣泛應用于各種圖形相關的領域,從古老的皮影戲、套色印刷術,到現代電影/游戲工業以及虛擬現實領域等等。而分層Canvas只是分層渲染思想在Canvas動畫上的一個基礎應用。

          分層Canvas的核心理念是,動態頁面中的每種元素(層)對于渲染頻率的需求是不同的。對于許多金融會計等大數據行業的從業者來說,主要數據內容的變化頻率和幅度較大(他們通常面臨數據變動和頻繁計算),而背景表格樣式的變化頻率或幅度相對較小(基本不變,或者變化緩慢,或者僅在特定時機變化)。因此,需要頻繁更新和重繪數據,但對于背景,可能只需要繪制一次,或者每隔200毫秒才重繪一次,而沒有必要每16毫秒就重繪一次。

          視野之外的繪制

          在許多情況下,Canvas 僅僅作為數據展示頁面的一部分,充當著一個“窗口”的角色。如果在每次數據更新時,都將所有數據完全繪制到 Canvas 上,很可能會出現大量內容繪制到Canvas 范圍之外的情況。雖然調用了繪制 API,但實際上并沒有產生任何效果。

          因此,判斷對象是否位于 Canvas 范圍內需要進行額外的計算(例如,需要通過對游戲角色的全局模型矩陣求逆來得出對象的世界坐標,這是一項相對耗時的操作),同時也會增加代碼的復雜性。因此,關鍵是是否需要這樣做。

          通過在本地代碼中進行測試,比較了在視野內和視野外分別繪制100萬個圓的耗時。在視野內繪制耗時8936ms,而在視野外繪制耗時2540ms。考慮到計算和繪制之間的耗時差距在3~4個數量級,因此通過計算來判斷并避免繪制視野外的內容是一種非常有效的方法。

          五. Canvas的應用

          之前探討了SVG和Canvas的繪制性能差異以及Canvas常見的優化方法。知道,對于使用快速模式渲染的Canvas來說,瀏覽器的每次重繪都是由代碼驅動的,無須進行多層解析,因此它的速度非常快。除了速度快之外,Canvas的靈活性也顯著優于DOM。可以通過代碼精確控制何時以及如何繪制出期望的效果。

          在資源消耗方面,DOM的駐留模式意味著場景中的每一個新增元素都會導致額外的內存消耗,而Canvas則沒有這個問題。這種差異在頁面元素數量增多時尤為明顯。

          在Canvas出現之前,前端渲染表格只能通過構建復雜的DOM來實現。然而,這種方式會導致瀏覽器性能成為Web應用的瓶頸,許多開發人員因此放棄了在瀏覽器上實現電子表格的想法。

          Canvas出現后,其快速模式帶來的出色性能優勢成為了一大亮點,大量、復雜的DOM渲染處理所帶來的性能問題因此有了解決之道。

          回到電子表格的應用場景,現在已經出現了使用Canvas繪制畫布的表格組件。這類組件在渲染數據層時無須重復創建和銷毀DOM元素,而且在畫布的繪制過程中受到的限制也比DOM元素渲染更少。其中,葡萄城公司的純前端表格控件——SpreadJS就用到了Canvas實現表格繪制,除了表格之外,Canvas也為數字孿生可視化大屏、頁面游戲等應用場景帶來了變革(如下圖所示)。

          六、總結

          本文通過介紹Canvas的原理、Canvas的重要性、Canvas在計算與渲染上的作用、Canvas渲染性能優勢和Canvas的應用這五個部分,全面而系統地闡述了HTML Canvas在高性能渲染方面的相關知識和技巧。希望讀者通過閱讀本文能夠深入了解Canvas的基本原理和特性,認識到Canvas在Web開發中的重要性,并掌握Canvas在計算與渲染上的作用。

          思維新建站官網:jz.inspinovation.com

          文|李掌柜

          前面給大家介紹了《HTML5移動前端性能優化之加載優化》,今天來向大家介紹如何從網頁渲染的層面來優化HTML5前端性能。

          一、HTML5使用viewport

          通俗的講,移動設備上的viewport就是設備的屏幕上能用來顯示我們的網頁的那一塊區域,在具體一點,就是瀏覽器上(也可能是一個app中的webview)用來顯示網頁的那部分區域,但viewport又不局限于瀏覽器可視區域的大小,它可能比瀏覽器的可視區域要大,也可能比瀏覽器的可視區域要小。在默認情況下,一般來講,移動設備上的viewport都是要大于瀏覽器可視區域的,這是因為考慮到移動設備的分辨率相對于桌面電腦來說都比較小,所以為了能在移動設備上正常顯示那些傳統的為桌面瀏覽器設計的網站,移動設備上的瀏覽器都會把自己默認的viewport設為980px或1024px(也可能是其它值,這個是由設備自己決定的),但帶來的后果就是瀏覽器會出現橫向滾動條,因為瀏覽器可視區域的寬度是比這個默認的viewport的寬度要小的。下圖列出了一些設備上瀏覽器的默認viewport的寬度。

          二、減少DOM節點

          當解析的html文件很大時,生成DOM樹占用內存較大,同時遍歷(不更新)元素耗時也更長。但這都不是重點,DOM的核心問題是:DOM修改導致的頁面重繪、重新排版!重新排版是用戶阻塞的操作,同時,如果頻繁重排,CPU使用率也會猛漲!

          三、盡量使用CSS3動畫

          CSS雖然是由瀏覽器實現,按理在瀏覽器支持的前提下性能會更好,然而使用者如果加入了其他干擾,發生頻繁的重繪或者回流,自然性能就差了。

          四、Touchmove 和Scroll事件會導致多次渲染

          類似touchmove,scroll這類的事件可導致多次渲染,對于這種事件可以通過以下手段進行優化:

          1.使用requestAnimationFrame監聽幀變化,使得在正確的時間進行渲染

          2.增加響應變化的時間間隔,減少重繪次數。

          五、GPU加速

          觸發GPU加速的方式有:CSS3 transitions、CSS3 3D transforms、WebGL 3D 繪制、Video。

          GPU加速實際上是大幅減少了合成/繪制時間,從而大大地提高了頁面速度,但GPU加速有自己的缺點:

          過多的GPU層會帶來性能開銷,主要原因是使用GPU加速其實是利用了GPU層的緩存,讓渲染資源可以重復使用,所以一旦層多了,緩存增大,就會引起別的性能問題。


          主站蜘蛛池模板: 国模吧一区二区三区| 国产伦精品一区二区三区无广告| 能在线观看的一区二区三区| 亚洲高清美女一区二区三区| 国产精品一区二区av| 国产成人精品一区在线| 午夜视频一区二区| 日韩精品久久一区二区三区 | 国产精品一区二区av不卡| 无码一区二区三区爆白浆| 国产精品久久久久一区二区三区| 国产福利日本一区二区三区| 四虎成人精品一区二区免费网站| 无码丰满熟妇浪潮一区二区AV| 无码人妻aⅴ一区二区三区| 一区二区三区日本视频| 国产精品无码一区二区三级| 亚洲av无码片vr一区二区三区| 精品国产日韩一区三区| 日韩一区二区久久久久久| 精品人妻中文av一区二区三区| 国产成人AV区一区二区三| 黑人大战亚洲人精品一区| 亚洲AV无码一区二区乱子仑| 亚洲福利视频一区二区| 国产精品高清视亚洲一区二区 | 亚洲一区二区观看播放| 日美欧韩一区二去三区| 日韩国产精品无码一区二区三区| 精品国产日韩一区三区| 精品日韩亚洲AV无码一区二区三区 | 在线观看一区二区三区av| 丝袜人妻一区二区三区| 国产精品第一区揄拍无码| 无码国产精品一区二区免费| 国产午夜三级一区二区三| 视频一区视频二区日韩专区| 日韩一区二区视频| 国内自拍视频一区二区三区| 国产成人无码精品一区二区三区 | 国产在线一区二区综合免费视频|