瀏覽器渲染性能優化

渲染性能

頁面不只要快速加載,並且要順暢地運行;滾動應與手指的滑動同樣快,而且動畫和交互應如絲綢般順滑。css

60fps 與設備刷新率

目前大多數設備的屏幕刷新率爲 60 /。所以,若是在頁面中有一個動畫或漸變效果,或者用戶正在滾動頁面,那麼瀏覽器渲染動畫或頁面的每一幀的速率也須要跟設備屏幕的刷新率保持一致。html

其中每一個幀的預算時間僅比 16 毫秒多一點 (1 秒/ 60 = 16.66 毫秒)。但實際上,瀏覽器有整理工做要作,所以全部工做須要在 10 毫秒內完成。若是沒法符合此預算,幀率將降低,而且內容會在屏幕上抖動(judders)。此現象一般稱爲卡頓(jank,會對用戶體驗產生負面影響。jquery

像素管道(The pixel pipeline)git

在工做時須要瞭解並注意五個主要區域,這些是擁有最大控制權的部分,也是像素至屏幕管道中的關鍵點:github

 

  • JavaScript。通常來講,會使用 JavaScript 來實現一些視覺變化的效果。好比用 jQuery 的 animate 函數作一個動畫、對一個數據集進行排序或者往頁面裏添加一些 DOM 元素等。除了 JavaScript,還有其餘一些經常使用方法也能夠實現視覺變化效果,好比:CSS Animations、Transitions 和 Web Animation API。
  • 樣式計算Sytle calculations。This is the process of figuring out which CSS rules apply to which elements based on matching selectors, for example, .headline or .nav > .nav__item. From there, once rules are known, they are applied and the final styles for each element are calculated.
  • 佈局。在知道對一個元素應用哪些規則以後,瀏覽器便可開始計算它要佔據的空間大小及其在屏幕的位置。網頁的佈局模式意味着一個元素可能影響其餘元素,例如 <body> 元素的寬度通常會影響其子元素的寬度以及樹中各處的節點,所以對於瀏覽器來講,佈局過程是常常發生的。
  • 繪製。繪製是填充像素的過程。它涉及繪出文本、顏色、圖像、邊框和陰影,包括元素的每一個可視部分。繪製通常是在多個表面(一般稱爲層layers)上完成的。
  • 合成。因爲頁面的各部分可能被繪製到多層,由此它們須要按正確順序繪製到屏幕上,以便正確渲染頁面。對於與另外一元素重疊的元素來講,這點特別重要,由於一個錯誤可能使一個元素錯誤地出如今另外一個元素的上層。

管道的每一個部分都有機會產生卡頓,所以務必準確瞭解代碼觸發管道的哪些部分。瀏覽器

不必定每幀都老是會通過管道每一個部分的處理。實際上,無論是使用 JavaScript、CSS 仍是網絡動畫,在實現視覺變化時,管道針對指定幀的運行一般有三種方式:安全

1. JS / CSS > 樣式 > 佈局 > 繪製 > 合成網絡

 

若是修改元素的「layout」屬性,即改變了元素的幾何屬性(例如寬度、高度等),那麼瀏覽器將必須檢查全部其餘元素,而後「自動重排」頁面(reflow the page)。任何受影響的部分都須要從新繪製,並且最終繪製的元素需進行合成。app

2. JS / CSS > 樣式 > 繪製 > 合成框架

 

若是修改「paint only」屬性(例如背景圖片、文字顏色或陰影等),即不會影響頁面佈局的屬性,則瀏覽器會跳過佈局,但仍將執行繪製。

3. JS / CSS > 樣式 > 合成

 

若是更改一個既不用從新佈局也不要從新繪製的屬性,則瀏覽器將只執行合成。這個最後的方式開銷最小,最適合於應用生命週期中的高壓力點,例如動畫或滾動。

性能是一種避免執行的藝術,而且使執行的任何操做盡量高效。 許多狀況下,這須要與瀏覽器配合,而不是跟它對着幹。 值得謹記的是,上面列出的各項管道工做在計算開銷上有所不一樣,一些任務比其餘任務的開銷要大!

優化 JavaScript 執行

JavaScript often triggers visual changes. Sometimes that's directly through style manipulations, and sometimes it's calculations that result in visual changes, like searching or sorting data.時機不當或長時間運行的 JavaScript 多是致使性能問題的常見緣由,應當設法儘量減小其影響。

JavaScript 性能分析能夠說是一門藝術,由於編寫的 JavaScript 代碼與實際執行的代碼徹底不像。現代瀏覽器使用 JIT 編譯器和各類各樣的優化和技巧來實現儘量快的執行,這極大地改變了代碼的動態性。

一些幫助應用很好地執行 JavaScript的事情:

  • 對於動畫效果的實現,避免使用 setTimeout 或 setInterval,使用 requestAnimationFrame。
  • 將長時間運行的 JavaScript 從主線程移到 Web Worker。
  • 使用小任務來執行對多個幀的 DOM 更改。
  • 使用 Chrome DevTools 的 Timeline 和 JavaScript 分析器來評估 JavaScript 的影響。

使用 requestAnimationFrame 來實現視覺變化

當屏幕正在發生視覺變化時,最好在幀的開頭執行操做。保證 JavaScript 在幀開始時運行的惟一方式是使用 requestAnimationFrame。

/**
 * If run as a requestAnimationFrame callback, this
 * will be run at the start of the frame.
 */
function updateScreen(time) {
  // Make visual updates here.
}
requestAnimationFrame(updateScreen);

框架或示例可能使用 setTimeout 或 setInterval 來執行動畫之類的視覺變化,但這種作法的問題是,回調函數在幀中的某個時點運行,可能恰好在幀的末尾,而這常常會使咱們丟失幀,致使卡頓。(composite等js的運行須要時間,會阻塞UI更新)。

 

事實上,jQuery 目前的默認 animate 行爲是使用 setTimeout!強烈建議打上補丁程序以使用 requestAnimationFrame

下降複雜性或使用 Web Worker

JavaScript 在瀏覽器的主線程上運行,剛好與樣式計算、佈局以及許多狀況下的繪製一塊兒運行。若是 JavaScript 運行時間過長,就會阻塞這些其餘工做,可能致使幀丟失。

所以,要妥善處理 JavaScript 什麼時候運行以及運行多久。例如,若是在滾動之類的動畫中,最好是想辦法使 JavaScript 保持在 3-4 毫秒的範圍內。超過此範圍,就可能要佔用太多時間。若是在空閒期間,則能夠沒必要那麼斤斤計較所佔的時間。

在許多狀況下,能夠將純計算工做移到 Web Worker,例如,不須要 DOM 訪問權限,數據操做或遍歷(例如排序或搜索),每每很適合這種模型,加載和模型生成也是如此。

var dataSortWorker = new Worker("sort-worker.js");
dataSortWorker.postMesssage(dataToSort);
// The main thread is now free to continue working on other things...
dataSortWorker.addEventListener('message', function(evt) {
   var sortedData = evt.data;
   // Update data on screen...
});

並不是全部工做都適合此模型:Web Worker 沒有 DOM 訪問權限。若是操做必須在主線程上執行,能夠考慮一種批量方法,將大型任務分割爲小任務,每一個小任務所佔時間不超過幾毫秒,而且在每幀的 requestAnimationFrame 處理程序內運行。

var taskList = breakBigTaskIntoMicroTasks(monsterTaskList);
requestAnimationFrame(processTaskList);
function processTaskList(taskStartTime) {
  var taskFinishTime;
  do {
    // Assume the next task is pushed onto a stack.
    var nextTask = taskList.pop();
    // Process nextTask.
    processTask(nextTask);
    // Go again if there’s enough time to do the next task.
    taskFinishTime = window.performance.now();
  } while (taskFinishTime - taskStartTime < 3);
  if (taskList.length > 0)
    requestAnimationFrame(processTaskList);
}

此方法會產生 UX 和 UI 後果,您將須要使用進度或活動指示器來確保用戶知道任務正在被處理。在任何狀況下,此方法都不會佔用應用的主線程,從而有助於主線程始終對用戶交互做出快速響應。

瞭解 JavaScript 的「frame tax」

在評估一個框架、庫或本身的代碼時,務必逐幀評估運行 JavaScript 代碼的開銷。當執行性能關鍵的動畫工做(例如變換或滾動)時,這點尤爲重要。

測量 JavaScript 開銷和性能狀況的最佳方法是使用 Chrome DevTools。一般,您將得到以下的簡單記錄:

 

The Main section provides a flame chart of JavaScript calls so you can analyze exactly which functions were called and how long each took.

若是發現有長時間運行的 JavaScript,則能夠在 DevTools 用戶界面的頂部啓用 JavaScript 分析器:

 


以這種方式分析 JavaScript 會產生開銷,所以必定只在想要更深刻了解 JavaScript 運行時特性時才啓用它。啓用此複選框後,如今能夠執行相同的操做,您將得到有關 JavaScript 中調用了哪些函數的更多信息:

 

有了這些信息以後,就能夠評估 JavaScript 對應用性能的影響,並開始找出和修正函數運行時間過長的熱點(hotspots)。如前所述,應當設法移除長時間運行的 JavaScript,或者若不能移除,則將其移到 Web Worker 中,騰出主線程繼續執行其餘任務。

避免微優化 JavaScript

知道瀏覽器執行一個函數版本比另外一個函數要快 100 倍可能會很酷,好比請求元素的offsetTop比計算getBoundingClientRect()要快,可是,您在每幀調用這類函數的次數幾乎老是不多。所以,把重點放在 JavaScript 性能的這個方面一般是白費勁。您通常只能節省零點幾毫秒的時間。

若是您開發的是遊戲或計算開銷很大的應用,則可能屬於本指南的例外狀況,由於您通常會將大量計算放入單個幀,在這種狀況下各類方法都頗有用。

簡而言之,慎用微優化,由於它們一般不會映射到您正在構建的應用類型。2/8法則,先從瓶頸處着手優化。

縮小樣式計算的範圍並下降其複雜性

經過添加和刪除元素,更改屬性、類或經過動畫來更改 DOM,都會致使瀏覽器從新計算元素樣式,在不少狀況下還會對頁面或頁面的一部分進行佈局(即自動重排)。This process is called computed style calculation.

計算樣式的第一部分是建立一組匹配選擇器,這實質上是瀏覽器計算出給指定元素應用哪些classes, pseudo-selectors and IDs。

第二部分涉及從匹配選擇器中獲取全部樣式規則,並計算出此元素的最終樣式。在 Blink(Chrome 和 Opera 的渲染引擎)中,這些過程的開銷至少在目前是大體相同的:

Roughly 50% of the time used to calculate the computed style for an element is used to match selectors,而另外一半時間用於從匹配的規則中構建 RenderStyle(computed style representation)。

  • 下降選擇器的複雜性;使用以類爲中心的方法,例如 BEM規範(Block-Element_Modifer)。
  • 減小必須計算其樣式的元素數量。

下降選擇器的複雜性

在最簡單的狀況下,在 CSS 中只有一個類的元素:

.title {
  /* styles */
}

可是,隨着項目的增加,將可能產生更復雜的 CSS,最終的選擇器可能變成這樣:

.box:nth-last-child(-n+1) .title {
  /* styles */
}

爲了知道是否須要應用樣式,瀏覽器實際上必須詢問「這是否爲有 title 類的元素,其父元素剛好是負第 N 個子元素加上 1 個帶 box 類的元素?」計算此結果可能須要大量時間,具體取決於所用的選擇器和相應的瀏覽器。特定的選擇器能夠更改成一個類:

.final-box-title {
  /* styles */
}

開發者可能對該類的名稱有疑問,但此工做對於瀏覽器而言要簡單得多。在上一版本中,爲了知道該元素是否爲其類型的最後一個,瀏覽器首先必須知道關於其餘元素的全部狀況,以及其後面是否有任何元素會是第 N 個最後子元素,這比簡單地將類選擇器與元素匹配的開銷要大得多。

生成render tree時,對於每一個DOM元素,必須在全部Style Rules中找到符合的 selector 並將對應的樣式規則進行合併。
css選擇器的解析是從右往左的,這樣公共樣式就在CSSOM樹的父節點上,更具體的樣式(選擇器更具體)會在子節點上,節點分支和遍歷次數都會變少。若是採用 left-to-right 的方式讀取css規則,那麼大多數規則讀到最後纔會發現是不匹配,作了不少無用功;而採起 right-to-left 的方式,只要發現最右邊選擇器不匹配,就直接捨棄,避免不少無效匹配。

減小要計算樣式的元素數量

另外一個性能考慮,在元素更改時須要計算的工做量對於許多樣式更新而言是更重要的因素。

In general terms, the worst case cost of calculating the computed style of elements is the number of elements multiplied by the selector count, because each element needs to be at least checked once against every style rule to see if it matches.

注:之前曾經是這樣:若是改變了(例如)body 元素上的一個類,則該頁的全部子元素將須要從新計算其計算樣式。如今有點不同:對於更改時會致使從新計算樣式的元素,某些瀏覽器維護一小組每一個這種元素獨有的規則。這意味着,根據元素在樹中的位置以及所改變的具體屬性,元素不必定須要從新計算。

樣式計算可能常常是直接針對少許目標元素,而不是聲明整個頁面無效。在現代瀏覽器中,這每每再也不是個問題,由於瀏覽器並不必定須要檢查一項更改可能影響的全部元素。另外一方面,較早的瀏覽器不必定針對此類任務進行了優化。應當儘量減小聲明爲無效的元素的數量

注:若是您熱衷於網頁組件,有一點值得注意,樣式計算在這方面稍有不一樣,由於默認狀況下樣式不會跨越 Shadow DOM 的邊界,而且範圍限於單個組件,而不是整個樹。可是,整體來看,一樣的概念仍然適用:規則簡單的小樹比規則複雜的大樹會獲得更高效地處理。

測量樣式從新計算的開銷

測量樣式從新計算的最簡單、最好的方法是使用 Chrome DevTools 的 Timeline 模式。首先,打開 DevTools,轉至 Timeline 選項卡,選中記錄並與您的網站交互。中止記錄後,將看到下圖所示狀況。

 

頂部的條表示每秒幀數,若是看到柱形超過較低的線,即 60fps 線,則存在長時間運行的幀。

 

若是一些滾動之類的交互或其餘交互時出現長時間運行的幀,則應當進一步審查。

若是出現較大的紫色塊,如上例所示,請點擊記錄瞭解到更多細節。

 

 

在此次抓取中,有一個長時間運行的從新計算樣式事件,其時間恰好超過 18 毫秒,而且剛好發生在滾動期間,致使用戶體驗到明顯的抖動。

若是點擊事件自己,將看到一個調用棧,精確指出了您的 JavaScript 中致使觸發樣式更改的位置。此外,還得到樣式受更改影響的元素數量(本例中恰好超過 400 個元素),以及執行樣式計算所花的時間。您可使用此信息來開始嘗試在代碼中查找修正點。

使用BEM規範

BEM的編碼方法實際上歸入了上述選擇器匹配的性能優點,由於它建議全部元素都有單個類,而且在須要層次結構時也歸入了類的名稱:

.list { }
.list__list-item { }

若是須要一些修飾符,像在上面咱們想爲最後一個子元素作一些特別的東西,就能夠按以下方式添加:

.list__list-item--last-child {}

若是您在尋找一種好方法來組織您的 CSS,則 BEM 真的是個很好的起點,不只從結構的角度如此,還由於樣式查找獲得了簡化。

避免大型、複雜的佈局和佈局抖動

佈局是瀏覽器計算各元素幾何信息的過程:元素的大小以及在頁面中的位置。 根據所用的 CSS、元素的內容或父級元素,每一個元素都將有顯式或隱含的大小信息。此過程在 Chrome、Opera、Safari 和 Internet Explorer 中稱爲佈局 (Layout)。 在 Firefox 中稱爲自動重排 (Reflow),但實際上其過程是同樣的。

與樣式計算類似,佈局開銷的直接考慮因素以下:

  1. 須要佈局的元素數量。
  2. 這些佈局的複雜性。
  • 佈局的做用範圍通常爲整個文檔。
  • DOM 元素的數量將影響性能,應儘量避免觸發佈局。
  • 評估佈局模型的性能;新版 Flexbox比舊版 Flexbox 或基於浮動的佈局模型更快。
  • Avoid forced synchronous layouts and layout thrashing; read style values then make style changes.

儘量避免佈局操做

當更改樣式時,瀏覽器會檢查更改是否須要計算佈局,以及是否須要更新渲染樹。幾何屬性(如寬度、高度、左側或頂部)的更改都須要佈局計算。

.box {
  width: 20px;
  height: 20px;
}
/** Changing width and height triggers layout. */
.box--expanded {
  width: 200px;
  height: 350px;
}

佈局幾乎老是做用到整個文檔。 若是有大量元素,將須要很長時間來算出全部元素的位置和尺寸。

若是沒法避免佈局,關鍵仍是要使用 Chrome DevTools 來查看佈局要花多長時間,並肯定佈局是不是形成瓶頸的緣由。首先,打開 DevTools,選擇「Timeline」標籤,點擊「record」按鈕,而後與您的網站交互。當您中止記錄時,將看到網站表現狀況的詳細分析:

 

在仔細研究上例中的框架時,咱們看到超過 20 毫秒用在佈局上,當咱們在動畫中設置 16 毫秒來獲取屏幕上的幀時,此佈局時間太長。您還能夠看到,DevTools 將說明樹的大小(本例中爲 1618 個元素)以及須要佈局的節點數。

使用 flexbox 而不是較早的佈局模型

網頁有各類佈局模型,一些模式比其餘模式受到更普遍的支持。最先的 CSS 佈局模型使咱們可以在屏幕上對元素進行相對、絕對定位或經過浮動元素定位。

下面的屏幕截圖顯示了在 1,300 個框上使用浮動的佈局開銷。固然,這是一我的爲的例子,由於大多數應用將使用各類手段來定位元素。

 

 

若是咱們更新此示例以使用 Flexbox(Web 平臺的新模型),則出現不一樣的狀況:

 

如今,對於相同數量的元素和相同的視覺外觀,佈局的時間要少得多(本例中爲分別 3.5 毫秒和 14 毫秒)。務必記住,對於某些狀況,可能沒法選擇 Flexbox,由於它沒有浮動那麼受支持,可是在可能的狀況下,至少應研究佈局模型對網站性能的影響,而且採用最大程度減小網頁執行開銷的模型。

在任何狀況下,無論是否選擇 Flexbox,都應當在應用的高壓力點期間嘗試徹底避免觸發佈局

避免強制同步佈局

將一幀送到屏幕會採用以下順序:

 

首先 JavaScript 運行,而後計算樣式,而後佈局。可是,JavaScript 在更改元素樣式後,獲取其幾何屬性的值,此時會強制瀏覽器應用新樣式提早執行佈局,值後才能獲取幾何屬性值。這被稱爲強制同步佈局(forced synchronous layout

要記住的第一件事是,在 JavaScript 運行時,來自上一幀的全部舊佈局值是已知的,而且可供您查詢。所以,若是(例如)您要在幀的開頭寫出一個元素(讓咱們稱其爲「框」)的高度,可能編寫一些以下代碼:

// Schedule our function to run at the start of the frame.
requestAnimationFrame(logBoxHeight);
function logBoxHeight() {
  // Gets the height of the box in pixels and logs it out.
  console.log(box.offsetHeight);
}

若是在請求此框的高度以前,已更改其樣式,就會出現問題:

function logBoxHeight() {
  box.classList.add('super-big');    //樣式更改後,瀏覽器必須先應用新的樣式(重繪)以後才能獲取當前的值,有時是多作無用功
  // Gets the height of the box in pixels and logs it out.
  console.log(box.offsetHeight);
}

如今,爲了得到框的高度,瀏覽器必須先應用樣式更改(因爲增長了 super-big 類),而後運行佈局,這時才能返回正確的高度。這是沒必要要的,而且可能開銷很大。

所以,始終應先批量讀取樣式並執行(瀏覽器可使用上一幀的佈局值),而後執行任何賦值操做。

以上函數應爲:

function logBoxHeight() {
  // Gets the height of the box in pixels and logs it out.
  console.log(box.offsetHeight);
  box.classList.add('super-big');
}

大部分狀況下,並不須要先應用新樣式而後查詢值,使用上一幀的值就足夠了。與瀏覽器同步(或比其提早)運行樣式計算和佈局可能成爲瓶頸。

避免佈局超負荷(thrashing)

有一種方式會使強制同步佈局更糟:連續執行大量這種強制佈局。以下:

function resizeAllParagraphsToMatchBlockWidth() {
  // Puts the browser into a read-write-read-write cycle.
  for (var i = 0; i < paragraphs.length; i++) {
    paragraphs[i].style.width = box.offsetWidth + 'px';
  }
}

此代碼循環處理一組段落,並設置每一個段落的寬度以匹配一個稱爲「box」的元素的寬度。這看起來沒有害處,但問題是循環的每次迭代讀取一個樣式值 (box.offsetWidth),而後當即使用此值來更新段落的寬度 (paragraphs[i].style.width)。在循環的下次迭代時,瀏覽器必須考慮樣式已更改這一事實,由於 offsetWidth 是上次請求的(在上一次迭代中),因此它必須應用更改的樣式,而後運行佈局。每次迭代都將出現此問題!

此示例的修正方法仍是先讀取值,而後寫入值:

// Read.
var width = box.offsetWidth;
function resizeAllParagraphsToMatchBlockWidth() {
  for (var i = 0; i < paragraphs.length; i++) {
    // Now write.
    paragraphs[i].style.width = width + 'px';
  }
}

若是要保證安全,應當查看 FastDOM,它會自動批處理讀取和寫入,應當能防止意外觸發強制同步佈局或佈局抖動。

簡化繪製的複雜度、減少繪製區域

繪製是填充像素的過程,像素最終合成到用戶的屏幕上。 它每每是管道中運行時間最長的任務,應儘量避免此任務。

  • 除 transform 或 opacity 屬性以外,更改任何屬性始終都會觸發繪製。
  • 繪製一般是像素管道中開銷最大的部分,應儘量避免繪製。
  • 經過layer promotion和動畫的編排來減小繪製區域。
  • 使用 Chrome DevTools paint profile來評估繪製的複雜性和開銷;應儘量下降複雜性並減小開銷。

觸發佈局與繪製

若是觸發佈局,則老是會觸發繪製,由於更改任何元素的幾何屬性意味着其像素須要修正!

 

若是更改非幾何屬性,例如背景、文本或陰影,也可能觸發繪製。在這些狀況下,不須要佈局,而且管道將以下所示:

 

使用 Chrome DevTools 快速肯定繪製瓶頸

 

您可使用 Chrome DevTools 來快速肯定正在繪製的區域。打開 DevTools,按下鍵盤上的 Esc 鍵。在出現的面板中,轉到「rendering」標籤,而後選中「Show paint rectangles」。

打開此選項後,每次發生繪製時,Chrome 將讓屏幕閃爍綠色。若是看到整個屏幕閃爍綠色,或看到不該繪製的屏幕區域,則應當進一步研究。

 

Chrome DevTools Timeline 中有一個選項提供更多信息:繪製分析器。要啓用此選項,轉至 Timeline,而後選中頂部的「Paint」框。須要注意的是,請務必僅在嘗試分析繪製問題時纔打開此選項,由於它會產生開銷,而且會影響性能分析結果。最好是在想要更深刻了解具體繪製內容時使用。

 

完成了上述設置以後,如今能夠運行 Timeline 錄製,而且繪製記錄將包含更多的細節。經過點擊一幀的繪製記錄,您將進入該幀的繪製分析器:

點擊繪製分析器將調出一個視圖,您能夠查看所繪製的元素、所花的時間,以及所需的各個繪製調用:

 

此分析器顯示區域和複雜性(實際上就是繪製所花的時間),若是不能選擇避免繪製,這兩個都是能夠設法修正的方面。

提高移動或淡出的元素

繪製並不是老是繪製到內存中的單個圖像。事實上,在必要時瀏覽器能夠繪製到多個圖像或合成層(compositor layers)。

 

此方法的優勢是,按期重繪的或經過變形在屏幕上移動的元素,能夠在不影響其餘元素的狀況下進行處理。Sketch、GIMP 或 Photoshop 之類的藝術文件也是如此,各個層能夠在彼此的上面處理併合成,以建立最終圖像。

建立新層的最佳方式是使用 will-change CSS 屬性。此方法在 Chrome、Opera 和 Firefox 上有效,而且經過 transform 的值將建立一個新的合成器層:

.moving-element {
  will-change: transform;
}

對於不支持 will-change 但受益於層建立的瀏覽器,例如 Safari 和 Mobile Safari,須要使用3D 變形來強制建立一個新層:

.moving-element {
  transform: translateZ(0);
}

但須要注意的是:不要建立太多層,由於每層都須要內存和管理開銷。

若是已將一個元素提高到一個新層,可以使用 DevTools 確認這樣作已帶來性能優點。請勿在不分析的狀況下提高元素。

減小繪製區域

然而有時,雖然提高元素,卻仍須要繪製工做。繪製問題的一個大挑戰是,瀏覽器將兩個須要繪製的區域聯合在一塊兒,而這可能致使整個屏幕重繪。所以,若是頁面頂層有一個固定標頭,而在屏幕底部還有正在繪製的元素,則整個屏幕可能最終要重繪。

減小繪製區域每每是編排動畫和變換,使其不過多重疊,或設法避免對頁面的某些部分設置動畫。

下降繪製的複雜性

 

在談到繪製時,一些繪製比其餘繪製的開銷更大。例如,繪製任何涉及模糊(例如陰影)的元素所花的時間將比(例如)繪製一個紅框的時間要長。可是,對於 CSS 而言,這點並不老是很明顯:background: red; 和 box-shadow: 0, 4px, 4px, rgba(0,0,0,0.5); 看起來不必定有大相徑庭的性能特性,但確實很不相同。

利用上述繪製分析器,您能夠肯定是否須要尋求其餘方式來實現效果。問問本身,是否可能使用一組開銷更小的樣式或替代方式來實現最終結果。

您要儘量的避免繪製的發生,特別是在動畫效果中。由於每幀 10 毫秒的時間預算通常來講是不足以完成繪製工做的,尤爲是在移動設備上。

相關文章
相關標籤/搜索