Heim > Web-Frontend > js-Tutorial > Hauptteil

Optimierung der Browser-Rendering-Leistung

巴扎黑
Freigeben: 2017-06-26 11:53:49
Original
1888 Leute haben es durchsucht

Rendering-Leistung

Seiten sollten nicht nur schnell geladen werden, sondern auch reibungslos funktionieren; das Scrollen sollte so schnell wie eine Fingerbewegung sein, und Animationen und Interaktionen sollten so reibungslos wie Seide sein.

60fps und Geräteaktualisierungsrate

Derzeit beträgt die Bildschirmaktualisierungsrate der meisten Geräte 60 mal/ Sekunden. Wenn die Seite also eine Animation oder einen Farbverlaufseffekt enthält oder der Benutzer einen Bildlauf auf der Seite durchführt, muss die Geschwindigkeit, mit der der Browser jeden Frame der Animation oder Seite rendert, mit der Aktualisierungsrate des Gerätebildschirms übereinstimmen.

Die budgetierte Zeit für jeden Frame beträgt etwas mehr als 16 Millisekunden (1 Sekunde / 60 = 16,66 Millisekunden). Aber in Wirklichkeit muss der Browser einige Aufräumarbeiten erledigen, sodass die gesamte Arbeit innerhalb von 10 Millisekunden erledigt sein muss. Wenn dieses Budget nicht eingehalten werden kann, sinken die Frameraten und die Inhalte ruckeln auf dem Bildschirm. Dieses Phänomen wird oft als Jank (Jank) bezeichnet und wirkt sich negativ auf das Benutzererlebnis aus.

Die Pixelpipeline

Es gibt fünf Hauptbereiche, die Sie bei Ihrer Arbeit kennen und beachten sollten. Dies sind die Teile, die die meiste Kontrolle haben und Schlüsselpunkte in der Pixel-zu-Bildschirm-Pipeline sind:

  • JavaScript. Im Allgemeinen wird JavaScript verwendet, um einige visuelle Änderungen zu erzielen. Verwenden Sie beispielsweise die Animationsfunktion von jQuery, um eine Animation zu erstellen, einen Datensatz zu sortieren oder der Seite einige DOM-Elemente hinzuzufügen. Neben JavaScript gibt es noch andere gängige Methoden zum Erzielen visueller Änderungen, z. B. CSS-Animationen, Übergänge und die Webanimations-API.

  • StilberechnungenSytle-Berechnungen. Dabei wird anhand passender Selektoren ermittelt, welche CSS-Regeln für welche Elemente gelten, z. B. .headline oder .nav > Sobald die Regeln bekannt sind, werden sie angewendet und die endgültigen Stile für jedes Element festgelegt werden berechnet.

  • Layout. Nachdem bekannt ist, welche Regeln für ein Element gelten, kann der Browser damit beginnen, zu berechnen, wie viel Platz es einnehmen wird und welche Position es auf dem Bildschirm hat. Der Layoutmodus einer Webseite bedeutet, dass sich ein Element auf andere Elemente auswirken kann. Beispielsweise wirkt sich die Breite des -Elements im Allgemeinen auf die Breite seiner untergeordneten Elemente und Knoten überall im Baum aus Prozess kommt häufig vor.

  • Zeichnen . Beim Zeichnen werden Pixel ausgefüllt. Dabei geht es um das Zeichnen von Text, Farben, Bildern, Rändern und Schatten, einschließlich aller sichtbaren Teile eines Elements. Das Zeichnen erfolgt normalerweise auf mehreren Oberflächen (oft als Ebenen bezeichnet).

  • Synthetisieren. Da Teile der Seite möglicherweise auf mehreren Ebenen gezeichnet werden, müssen sie in der richtigen Reihenfolge auf dem Bildschirm gezeichnet werden, damit die Seite korrekt gerendert wird. Dies ist besonders wichtig für Elemente, die ein anderes Element überlappen, da ein Fehler dazu führen kann, dass ein Element falsch über einem anderen angezeigt wird.

Jeder Teil der Pipeline kann zu Verzögerungen führen. Daher ist es wichtig, genau zu wissen, welche Teile der Pipeline Ihr Code auslöst.

Nicht jeder Frame durchläuft immer jeden Teil der Pipeline. Unabhängig davon, ob Sie JavaScript, CSS oder Webanimationen verwenden, gibt es normalerweise drei Möglichkeiten, die Pipeline für einen bestimmten Frame auszuführen:

1 > Zeichnen > Synthese

Wenn Sie das „Layout“-Attribut eines Elements ändern, d. h. die geometrischen Eigenschaften des Elements (wie Breite, Höhe, usw.), dann muss der Browser alle anderen Elemente überprüfen und dann automatisch „die Seite umfließen“ lassen. Alle betroffenen Teile müssen neu lackiert werden und die endgültig lackierten Elemente müssen zusammengesetzt werden.

2. JS/CSS > Compositing

Textfarbe oder -schatten usw.), d. h. Eigenschaften, die sich nicht auf das Layout der Seite auswirken, überspringt der Browser das Layout, führt aber dennoch das Zeichnen aus.

3. JS/CSS > Composition

Wenn Sie eine Eigenschaft ändern, die weder Relayout noch Repaint erfordert, erfolgt nur Compositing durchgeführt. Dieser letzte Ansatz verursacht den geringsten Overhead und eignet sich am besten für stark beanspruchte Punkte im Anwendungslebenszyklus, wie z. B. Animationen oder Scrollen.

Leistung ist die Kunst, die Ausführung zu vermeiden

und jeden durchgeführten Vorgang so effizient wie möglich zu gestalten. In vielen Fällen erfordert dies das Arbeiten mit dem Browser und nicht dagegen. Beachten Sie, dass die verschiedenen oben aufgeführten Pipeline-Jobs einen unterschiedlichen Rechenaufwand haben, wobei einige Aufgaben teurer sind als andere!

JavaScript-Ausführung optimieren

JavaScript löst häufig visuelle Änderungen aus, manchmal sind es direkte Berechnungen, die zu visuellen Änderungen führen, z. B. falsches Timing oder lange Ausführung von JavaScript kann eine häufige Ursache für Leistungsprobleme sein und Sie sollten versuchen, die Auswirkungen zu minimieren.

JavaScript-Leistungsanalyse kann als eine Kunst bezeichnet werden, da der von Ihnen geschriebene JavaScript-Code nichts mit dem Code zu tun hat, der tatsächlich ausgeführt wird. Moderne Browser nutzen JIT-Compiler und eine Vielzahl von Optimierungen und Tricks, um eine möglichst schnelle Ausführung zu erreichen, was die Dynamik des Codes stark verändert.

Einige Dinge, die Ihrer Anwendung helfen, JavaScript gut auszuführen:

  • Vermeiden Sie für Animationseffekte die Verwendung von setTimeout oder setInterval und verwenden Sie requestAnimationFrame.

  • Verschieben Sie lang laufendes JavaScript vom Hauptthread in einen Web Worker.

  • Verwenden Sie kleine Aufgaben, um DOM-Änderungen über mehrere Frames hinweg durchzuführen.

  • Verwenden Sie die Zeitleiste und den JavaScript-Profiler von Chrome DevTools, um die Auswirkungen von JavaScript zu bewerten.

Verwenden Sie requestAnimationFrame, um visuelle Änderungen zu erzielen

Wenn auf dem Bildschirm visuelle Änderungen vorgenommen werden, ist es am besten, Vorgänge am Anfang des Frames auszuführen . Die einzige Möglichkeit, sicherzustellen, dass JavaScript am Anfang eines Frames ausgeführt wird, ist die Verwendung von 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);
Nach dem Login kopieren

Ein Framework oder Beispiel kann setTimeout oder setInterval verwenden, um visuelle Änderungen wie Animationen durchzuführen, aber das Problem bei diesem Ansatz besteht darin, dass die Callback-Funktion an einem bestimmten Punkt aufgerufen wird Der Frame Der Lauf befindet sich möglicherweise direkt am Ende des Frames, was häufig dazu führt, dass wir Frames auslassen, was zu Verzögerungen führt. (Das Ausführen von JS wie Composite nimmt Zeit in Anspruch und blockiert Aktualisierungen der Benutzeroberfläche.)

Tatsächlich ist das aktuelle Standardanimationsverhalten von jQuery die Verwendung von setTimeout. Es wird dringend empfohlen, einen Patch für die Verwendung von requestAnimationFrame durchzuführen.

Reduzieren Sie die Komplexität oder verwenden Sie einen Web Worker

JavaScript wird im Hauptthread des Browsers ausgeführt, zusammen mit Stilberechnungen, Layout und in vielen Fällen Zeichnungen. Wenn JavaScript zu lange ausgeführt wird, blockiert es diese andere Arbeit, was möglicherweise zu ausgelassenen Frames führt.

Überlegen Sie also gut, wann und wie lange Ihr JavaScript ausgeführt wird. Wenn Sie beispielsweise eine Animation wie Scrollen ausführen, ist es am besten, eine Möglichkeit zu finden, das JavaScript im Bereich von 3-4 ms zu halten. Alles darüber hinaus kann zu viel Zeit in Anspruch nehmen. Wenn Sie frei sind, müssen Sie sich nicht so viele Gedanken über die Zeit machen.

In vielen Fällen ist es möglich, reine Rechenarbeit auf einen Web Worker zu verlagern, der z. B. keinen DOM-Zugriff, keine Datenmanipulation oder Durchquerung (wie Sortieren oder Suchen) erfordert, was in der Regel gut geeignet ist Dieses Modell, Laden und Modellieren. Das Gleiche gilt für die Generierung.

var dataSortWorker = new Worker("sort-worker.js?1.1.11");
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...});
Nach dem Login kopieren

Nicht alle Jobs sind für dieses Modell geeignet: Web Worker haben keinen DOM-Zugriff. Wenn der Vorgang im Hauptthread ausgeführt werden muss, sollten Sie einen Batch-Ansatz in Betracht ziehen, der die große Aufgabe in kleinere Aufgaben aufteilt, die jeweils nicht länger als ein paar Millisekunden dauern und innerhalb des requestAnimationFrame-Handlers für jeden Frame ausgeführt werden.

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);
}
Nach dem Login kopieren

Dieser Ansatz hat Konsequenzen für UX und UI. Sie müssen einen Fortschritts- oder Aktivitätsindikator verwenden, um sicherzustellen, dass der Benutzer weiß, dass die Aufgabe verarbeitet wird. Diese Methode bindet unter keinen Umständen den Haupt-Thread der Anwendung und hilft dem Haupt-Thread, stets schnell auf Benutzerinteraktionen zu reagieren.

Erfahren Sie mehr über die „Frame-Steuer“ von JavaScript

Bewerten Sie beim Evaluieren eines Frameworks, einer Bibliothek oder Ihres eigenen Codes unbedingt den Overhead, der durch die Ausführung von JavaScript-Code auf Frame-für-Frame-Basis entsteht. Dies ist besonders wichtig, wenn leistungskritische Animationsarbeiten wie Transformationen oder Scrolls ausgeführt werden.

Der beste Weg, den JavaScript-Overhead und die Leistung zu messen, ist die Verwendung von Chrome DevTools. Normalerweise erhalten Sie einen einfachen Datensatz wie diesen:

Der Hauptabschnitt enthält ein Flammendiagramm der JavaScript-Aufrufe, sodass Sie genau analysieren können, welche Funktionen wie lange aufgerufen wurden

Wenn Sie JavaScript mit langer Laufzeit finden, können Sie den JavaScript-Analysator oben auf der DevTools-Benutzeroberfläche aktivieren:


In Auf diese Weise ist die Profilerstellung für JavaScript mit einem Mehraufwand verbunden. Aktivieren Sie sie daher nur, wenn Sie ein tieferes Verständnis der JavaScript-Laufzeitfunktionen wünschen. Wenn dieses Kontrollkästchen aktiviert ist, können Sie jetzt dasselbe tun und erhalten weitere Informationen darüber, welche Funktionen in JavaScript aufgerufen werden:

Mit diesen Informationen können Sie die Auswirkungen bewerten von JavaScript auf die Anwendungsleistung und beginnen, Hotspots zu identifizieren und zu korrigieren, bei denen die Ausführung von Funktionen zu lange dauert. Wie bereits erwähnt, sollten Sie versuchen, lang laufendes JavaScript zu entfernen. Wenn dies nicht möglich ist, verschieben Sie es in einen Web Worker, um den Hauptthread für die Ausführung anderer Aufgaben freizugeben.

Vermeiden Sie die Mikrooptimierung von JavaScript

Es könnte cool sein zu wissen, dass der Browser eine Version einer Funktion 100-mal schneller ausführt als eine andere, z. B. das Anfordern des OffsetTop von Ein Element als die Berechnung von getBoundingClientRect() ist schnell, aber die Häufigkeit, mit der Sie eine solche Funktion pro Frame aufrufen, ist fast immer sehr gering. Daher ist es oft vergebliche Mühe, sich auf diesen Aspekt der JavaScript-Leistung zu konzentrieren. Normalerweise sparen Sie nur ein paar Zehntel einer Millisekunde.

Wenn Sie ein Spiel oder eine rechenintensive Anwendung entwickeln, stellen Sie möglicherweise eine Ausnahme von diesem Leitfaden dar, da Sie normalerweise viele Berechnungen in einem einzigen Rahmen unterbringen. In diesem Fall sind verschiedene Methoden sehr nützlich.

Kurz gesagt: Verwenden Sie Mikrooptimierungen mit Vorsicht, da sie oft nicht auf die Art der App abgestimmt sind, die Sie erstellen. Gemäß der 2/8-Regel beginnen Sie mit der Optimierung zuerst am Engpass.

Einschränken des Umfangs und der Komplexität von Stilberechnungen

Ändern des DOM durch Hinzufügen und Entfernen von Elementen, Ändern von Attributen, Klassen oder durch Animationen führt dazu, dass der Browser die Berechnungen neu startet Elementstile und in vielen Fällen auch Layouts (d. h. automatischer Umfluss) der Seite oder eines Teils einer Seite. Dieser Vorgang wird als berechneter Stil bezeichnet Berechnung.

Der erste Teil der Berechnung eines Stils besteht darin, einen Satz passender Selektoren zu erstellen. Dabei handelt es sich im Wesentlichen darum, dass der Browser herausfindet, welche Klassen, Pseudoselektoren und IDs auf ein bestimmtes Element angewendet werden sollen.

Im zweiten Teil geht es darum, alle Stilregeln aus dem passenden Selektor abzurufen und den endgültigen Stil für dieses Element herauszufinden. In Blink (der Rendering-Engine für Chrome und Opera) ist der Overhead dieser Prozesse, zumindest im Moment, ungefähr gleich:

Ungefähr 50 % der früheren Zeit Die Berechnung des berechneten Stils für ein Element wird verwendet, um Selektoren abzugleichen, während die andere Hälfte der Zeit damit verbracht wird, einen RenderStyle (berechnete Stildarstellung) aus den Übereinstimmungsregeln zu erstellen.

  • Reduzieren Sie die Selektorkomplexität; verwenden Sie einen klassenzentrierten Ansatz wie die BEM-Spezifikation (Block-Element_Modifer).

  • Reduziert die Anzahl der Elemente, deren Stile berechnet werden müssen.

Reduzieren Sie die Selektorkomplexität

Im einfachsten Fall gibt es in CSS nur eine Klasse von Elementen:

.title {
/*styles */
}

Allerdings as As the Das Projekt wächst, möglicherweise wird komplexeres CSS erstellt und der endgültige Selektor sieht möglicherweise so aus:

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

Um zu wissen, ob ein Stil angewendet werden muss, muss der Browser tatsächlich fragen: „Ist dies ein Element mit Klassentitel, dessen übergeordnetes Element genau das negative N-te untergeordnete Element plus 1 Element ist.“ mit Klassenbox?“ Die Berechnung dieses Ergebnisses kann je nach verwendetem Selektor und entsprechendem Browser erhebliche Zeit in Anspruch nehmen. Ein bestimmter Selektor kann in eine Klasse geändert werden:

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

Entwickler haben möglicherweise Probleme mit dem Namen der Klasse, aber für Browser ist die Aufgabe viel einfacher. Um zu wissen, ob das Element das letzte Element seines Typs war, musste der Browser in der vorherigen Version zunächst alles über die anderen Elemente wissen und wissen, ob alle darauf folgenden Elemente das N-te letzte untergeordnete Element sein würden, was schneller war als einfaches Matching Klassenselektoren für Elemente sind viel teurer.

Beim Generieren des Renderbaums muss für jedes DOM-Element der passende Selektor in allen Stilregeln gefunden werden und die entsprechenden Stilregeln müssen zusammengeführt werden.
Der CSS-Selektor wird von rechts nach links analysiert, sodass sich der öffentliche Stil auf dem übergeordneten Knoten des CSSOM-Baums befindet und der spezifischere Stil (der Selektor ist spezifischer) auf dem untergeordneten Knoten und dem Knoten liegt Verzweigungen und Durchlaufzeiten werden sich kaum ändern. Wenn Sie CSS-Regeln mit der Links-nach-Rechts-Methode lesen, werden die meisten Regeln bis zum Ende als nicht übereinstimmend befunden, und bei Verwendung der Rechts-nach-Links-Methode wird viel unnötige Arbeit geleistet. Solange Sie feststellen, dass der Selektor ganz rechts nicht übereinstimmt. Wenn eine Übereinstimmung vorliegt, verwerfen Sie diese direkt, um viele ungültige Übereinstimmungen zu vermeiden.

Reduzieren Sie die Anzahl der Elemente, für die Stile berechnet werden

Ein weiterer Leistungsaspekt: ​​Der Arbeitsaufwand, der berechnet werden muss, wenn sich ein Element ändert, ist ein wichtigerer Faktor für viele Style-Updates.

Im Allgemeinen sind die Kosten für die Berechnung des berechneten Stils im ungünstigsten Fall Elemente ist die Anzahl der Elemente multipliziert mit der Selektoranzahl, weil Um dies zu sehen, muss jedes Element mindestens einmal anhand jeder Stilregel überprüft werden wenn es übereinstimmt.

Hinweis: Früher galt: Wenn Sie eine Klasse (zum Beispiel) am Body-Element geändert haben, mussten alle untergeordneten Elemente der Seite ihre berechneten Stile neu berechnen. Jetzt ist es etwas anders: Für Elemente, deren Stile bei Änderungen neu berechnet werden, verwalten einige Browser einen kleinen Satz Regeln, die für jedes dieser Elemente einzigartig sind. Dies bedeutet, dass abhängig von der Position des Elements im Baum und den spezifischen Eigenschaften, die geändert wurden, das Element nicht unbedingt neu berechnet werden muss.

Stilberechnungen können oft auf eine kleine Anzahl von Zielelementen ausgerichtet sein, anstatt die gesamte Seite ungültig zu machen. Bei modernen Browsern ist dies oft weniger problematisch, da Browser nicht unbedingt alle Elemente überprüfen müssen, auf die sich eine Änderung auswirken könnte. Andererseits sind ältere Browser nicht unbedingt für solche Aufgaben optimiert. Die Anzahl der als ungültig deklarierten Elemente sollte so weit wie möglich reduziert werden.

Hinweis: Wenn Sie sich für Webkomponenten interessieren, sollten Sie beachten, dass die Stilberechnungen in dieser Hinsicht etwas anders sind, da Stile standardmäßig nicht die Grenzen des Shadow DOM überschreiten und auf eine einzelne Komponente beschränkt sind statt Der ganze Baum. Insgesamt gilt jedoch immer noch das gleiche Konzept: Kleine Bäume mit einfachen Regeln werden effizienter verarbeitet als größere Bäume mit komplexeren Regeln.

Messung der Kosten für die Neuberechnung von Stilen

Der einfachste und beste Weg, die Neuberechnung von Stilen zu messen, ist die Verwendung des Zeitleistenmodus von Chrome DevTools. Öffnen Sie zunächst DevTools, gehen Sie zur Registerkarte „Zeitleiste“, wählen Sie „Aufzeichnung“ und interagieren Sie mit Ihrer Website. Nach dem Beenden der Aufnahme sehen Sie die in der folgenden Abbildung dargestellte Situation.

Der Balken oben stellt Bilder pro Sekunde dar. Wenn Sie sehen, dass der Balken die untere Linie, die 60-fps-Linie, überschreitet, gibt es lange laufende Bilder.


Wenn einige Interaktionen wie Scrollen oder andere Interaktionen lang laufende Frames haben, sollte dies weiter überprüft werden.

Wenn ein großer violetter Block erscheint, wie im Beispiel oben, klicken Sie auf „Aufzeichnen“, um weitere Details zu erhalten.

In diesem Crawl gibt es ein lang andauerndes Ereignis zum Neuberechnen des Stils, das etwas mehr als 18 Millisekunden dauert und zufällig beim Scrollen des Benutzers auftritt verspürt spürbaren Jitter.

Wenn Sie auf das Ereignis selbst klicken, wird ein Aufrufstapel angezeigt, der den Punkt in Ihrem JavaScript angibt, der die Auslösung der Stiländerung verursacht hat. Darüber hinaus erhalten Sie die Anzahl der Elemente, deren Stile von der Änderung betroffen sind (in diesem Fall etwas mehr als 400 Elemente), und die Zeit, die für die Stilberechnungen benötigt wurde. Mithilfe dieser Informationen können Sie mit der Suche nach Korrekturpunkten in Ihrem Code beginnen.

BEM-Spezifikation verwenden

Der Codierungsansatz von

BEM beinhaltet tatsächlich die oben erwähnten Leistungsvorteile des Selektor-Matchings, da er eine einzelne Klasse für alle Elemente vorschlägt und auch den Namen der Klasse enthält, wenn eine Hierarchie erforderlich ist:

.list { }
.list__list-item { }

Wenn Sie einige Modifikatoren benötigen, wie oben möchten wir etwas Besonderes für das letzte untergeordnete Element tun, können Sie es hinzufügen als folgt:

.list__list-item--last-child {}

Wenn Sie nach einer guten Möglichkeit suchen, Ihr CSS zu organisieren, ist BEM wirklich ein guter Ausgangspunkt, nicht nur aus struktureller Sicht, sondern auch, weil die Stilsuche vereinfacht wird.

Vermeiden Sie große, komplexe Layouts und Layout-Jitter

Layout ist der Prozess, mit dem der Browser die geometrischen Informationen jedes Elements berechnet: seine Größe und Position auf der Seite. Jedes Element verfügt abhängig vom verwendeten CSS, dem Inhalt des Elements oder seinem übergeordneten Element über explizite oder implizite Größeninformationen. Dieser Vorgang wird in Chrome, Opera, Safari und Internet Explorer als Layout bezeichnet. In Firefox wird es automatischer Reflow (Reflow) genannt, aber der Vorgang ist eigentlich derselbe.

Ähnlich wie bei Stilberechnungen sind die direkten Überlegungen zum Layout-Overhead wie folgt:

  1. Die Anzahl der Elemente, die angeordnet werden müssen.

  2. Die Komplexität dieser Layouts.

  • Der Umfang des Layouts umfasst in der Regel das gesamte Dokument.

  • Die Anzahl der DOM-Elemente wirkt sich auf die Leistung aus und auslösende Layouts sollten so weit wie möglich vermieden werden.

  • Bewerten Sie die Leistung von Layoutmodellen; neue Versionen von Flexbox sind schneller als ältere Versionen von Flexbox oder Float-basierte Layoutmodelle.

  • Vermeiden Sie erzwungene synchrone Layouts und Layout-Thrashing; Stilwerte lesen und dann Stiländerungen vornehmen.

Layoutoperationen so weit wie möglich vermeiden

Beim Ändern von Stilen prüft der Browser, ob die Änderungen erfordern ein Berechnungslayout und ob der Renderbaum aktualisiert werden muss. Änderungen an geometrische Eigenschaften (z. B. Breite, Höhe, links oder oben) erfordern alle Layoutberechnungen.

.box {
width: 20px;
height: 20px;
}
/**Ändern Breite und Höhe lösen das Layout aus. */
.box--expanded {
Breite: 200px;
Höhe: 350px;
}

Layout gilt fast immer für das gesamte Dokument. Wenn es eine große Anzahl von Elementen gibt, dauert es lange, die Positionen und Größen aller Elemente herauszufinden.

Wenn sich das Layout nicht vermeiden lässt, ist es wichtig, mithilfe der Chrome DevTools zu sehen, wie lange das Layout dauert, und festzustellen, ob das Layout die Ursache für den Engpass ist. Öffnen Sie zunächst DevTools, wählen Sie die Registerkarte „Timeline“, klicken Sie auf die Schaltfläche „Aufzeichnen“ und interagieren Sie mit Ihrer Site. Wenn Sie die Aufzeichnung beenden, sehen Sie eine detaillierte Analyse der Leistung Ihrer Website:

Wenn wir uns den Frame im obigen Beispiel genau ansehen, sehen wir, dass über 20 Millisekunden werden für das Layout aufgewendet. Wenn wir in der Animation 16 Millisekunden festlegen, um Frames auf dem Bildschirm anzuzeigen, dauert dieses Layout zu lange. Sie können auch sehen, dass DevTools die Größe des Baums (in diesem Fall 1618 Elemente) und die Anzahl der Knoten anzeigt, die angelegt werden müssen.

Verwenden Sie Flexbox anstelle älterer Layoutmodelle

Webseiten verfügen über verschiedene Layoutmodelle, von denen einige breiter unterstützt werden als andere. Die frühesten CSS-Layoutmodelle gaben uns die Möglichkeit, Elemente relativ, absolut oder über schwebende Elemente auf dem Bildschirm zu positionieren.

Der Screenshot unten zeigt den Layoutaufwand bei der Verwendung von Floats für 1.300 Boxen. Dies ist natürlich ein erfundenes Beispiel, da die meisten Anwendungen unterschiedliche Mittel zur Positionierung von Elementen verwenden.

Wenn wir dieses Beispiel aktualisieren, um Flexbox (das neue Modell für die Webplattform) zu verwenden, tritt eine andere Situation auf:

Jetzt dauert das Layout bei gleicher Anzahl von Elementen und gleichem visuellen Erscheinungsbild viel weniger Zeit (3,5 ms gegenüber 14 ms in diesem Fall). Es ist wichtig zu bedenken, dass Flexbox in manchen Fällen möglicherweise keine Option ist, da es nicht so unterstützt wird wie Floats. Wenn möglich, sollte man jedoch zumindest die Auswirkungen von Layoutmodellen auf die Website-Leistung untersuchen und ein Modell übernehmen, das den Ausführungsaufwand minimiert die Webseite.

Unabhängig davon, ob Sie sich für Flexbox entscheiden oder nicht, sollten Sie versuchen, das Auslösen von Layouts an Stellen mit hoher Belastung in Ihrer Anwendung überhaupt zu vermeiden !

Erzwungene Synchronisierung von Layouts vermeiden

将一帧送到屏幕会采用如下顺序:

 

首先 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);
}
Nach dem Login kopieren

如果在请求此框的高度之前,已更改其样式,就会出现问题:

function logBoxHeight() {
  box.classList.add('super-big');    //样式更改后,浏览器必须先应用新的样式(重绘)之后才能获取当前的值,有时是多做无用功
  // Gets the height of the box in pixels and logs it out.  console.log(box.offsetHeight);
}
Nach dem Login kopieren

现在,为了获得框的高度,浏览器必须先应用样式更改(由于增加了 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');
}
Nach dem Login kopieren

大部分情况下,并不需要先应用新样式然后查询值,使用上一帧的值就足够了。与浏览器同步(或比其提前)运行样式计算和布局可能成为瓶颈。

避免布局超负荷(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';
  }
}
Nach dem Login kopieren

此代码循环处理一组段落,并设置每个段落的宽度以匹配一个称为“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';
  }
}
Nach dem Login kopieren

如果要保证安全,应当查看 FastDOM,它会自动批处理读取和写入,应当能防止意外触发强制同步布局或布局抖动。

简化绘制的复杂度、减小绘制区域

绘制是填充像素的过程,像素最终合成到用户的屏幕上。 它往往是管道中运行时间最长的任务,应尽可能避免此任务。

  • 除 transform 或 opacity 属性之外,更改任何属性始终都会触发绘制。

  • 绘制通常是像素管道中开销最大的部分,应尽可能避免绘制。

  • 通过layer promotion和动画的编排来减少绘制区域。

  • 使用 Chrome DevTools paint profile来评估绘制的复杂性和开销;应尽可能降低复杂性并减少开销。

触发布局与绘制

如果触发布局,则总是会触发绘制,因为更改任何元素的几何属性意味着其像素需要修正!

 

如果更改非几何属性,例如背景、文本或阴影,也可能触发绘制。在这些情况下,不需要布局,并且管道将如下所示:

 

使用 Chrome DevTools 快速确定绘制瓶颈

Sie können Chrome DevTools verwenden, um schnell den Bereich zu bestimmen, den Sie zeichnen. Öffnen Sie DevTools und drücken Sie die Esc-Taste auf Ihrer Tastatur. Gehen Sie im angezeigten Bedienfeld zur Registerkarte „Rendering“ und aktivieren Sie „Farbrechtecke anzeigen“.

Wenn diese Option aktiviert ist, lässt Chrome den Bildschirm bei jedem Zeichnen grün blinken. Wenn Sie sehen, dass der gesamte Bildschirm grün blinkt oder Sie Bereiche auf dem Bildschirm sehen, die nicht gezeichnet werden sollten, sollten Sie weitere Untersuchungen durchführen.

In der Chrome DevTools-Timeline gibt es eine Option, die weitere Informationen bereitstellt: Draw Profiler. Um diese Option zu aktivieren, gehen Sie zur Timeline und aktivieren Sie das Kontrollkästchen „Malen“ oben. Bitte beachten Sie, dass Sie diese Option nur dann aktivieren, wenn Sie Zeichnungsprobleme analysieren möchten, da dies zu Mehraufwand führt und sich auf die Profilerstellungsergebnisse auswirken kann. Am besten verwenden Sie es, wenn Sie ein tieferes Verständnis davon erhalten möchten, was genau gezeichnet wird.

Nachdem Sie die oben genannten Einstellungen vorgenommen haben, können Sie nun die Timeline-Aufzeichnung ausführen und der Zeichnungsdatensatz enthält weitere Details. Durch Klicken auf den Zeichnungsdatensatz eines Rahmens gelangen Sie zum Zeichnungsanalysator für diesen Rahmen:

Durch Klicken auf den Zeichnungsanalysator wird eine Ansicht angezeigt, in der Sie die darin enthaltenen Elemente anzeigen können wurden gezogen, die benötigte Zeit und die einzelnen benötigten Draw-Aufrufe:

Dieser Analysator zeigt den Bereich und die Komplexität (tatsächlich die Zeit, die zum Zeichnen benötigt wird) an, wenn eine Vermeidung des Draws vorliegt keine Option, beides sind Aspekte, die korrigiert werden können.

Fördert verschobene oder verblasste Elemente

Das Zeichnen erfolgt nicht immer auf ein einzelnes Bild im Speicher. Tatsächlich kann der Browser bei Bedarf auf mehrere Bilder oder Compositor-Ebenen zeichnen.

Der Vorteil dieser Methode besteht darin, dass Elemente, die regelmäßig neu gezeichnet oder durch Transformationen auf dem Bildschirm verschoben werden, verarbeitet werden können, ohne andere Elemente zu beeinträchtigen. Das Gleiche gilt für Kunstdateien wie Sketch, GIMP oder Photoshop, bei denen einzelne Ebenen manipuliert und übereinander zusammengesetzt werden können, um das endgültige Bild zu erstellen.

Der beste Weg, eine neue Ebene zu erstellen, ist die Verwendung der CSS-Eigenschaft will-change. Diese Methode funktioniert auf Chrome, Opera und Firefox und erstellt eine neue Compositor-Ebene mit dem Wert transform:

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

Für Browser, die Will-Change nicht unterstützen, aber von der Ebenenerstellung profitieren, wie Safari und Mobile Safari, müssen Sie die 3D-Transformation verwenden, um die Erstellung einer neuen Ebene zu erzwingen:

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

Aber seien Sie vorsichtig: Erstellen Sie nicht zu viele Ebenen, da jede Ebene Speicher und Verwaltungsaufwand erfordert.

Wenn Sie ein Element auf eine neue Ebene heraufgestuft haben, verwenden Sie DevTools, um zu bestätigen, dass dies zu Leistungsvorteilen geführt hat. Bewerben Sie keine Elemente, ohne sie zu analysieren.

Zeichnungsfläche verkleinern

Aber manchmal sind trotz des Anhebens eines Elements immer noch Zeichenarbeiten erforderlich. Eine große Herausforderung bei Zeichenproblemen besteht darin, dass der Browser zwei Bereiche verbindet, die gezeichnet werden müssen, was dazu führen kann, dass der gesamte Bildschirm neu gezeichnet wird. Wenn Sie also oben auf der Seite eine feste Kopfzeile haben und am unteren Bildschirmrand Elemente zeichnen, wird möglicherweise der gesamte Bildschirm neu gezeichnet.

Um den Zeichenbereich zu verkleinern, geht es oft darum, Animationen und Transformationen so anzuordnen, dass sie sich nicht zu stark überlappen, oder zu versuchen, die Animation bestimmter Teile der Seite zu vermeiden.

Reduzieren Sie die Komplexität der Zeichnungen

Wenn es ums Zeichnen geht, sind einige Zeichnungen teurer als andere. Beispielsweise dauert das Zeichnen eines Elements mit Unschärfe (z. B. eines Schattens) länger als beispielsweise das Zeichnen eines roten Rahmens. Allerdings ist dies bei CSS nicht immer offensichtlich: background: red und box-shadow: 0, 4px, 4px, rgba(0,0,0,0.5); scheint nicht unbedingt völlig andere Leistungsmerkmale zu haben, ist es aber.

Mit dem Farbanalysator oben können Sie feststellen, ob Sie nach anderen Wegen suchen müssen, um den Effekt zu erzielen. Fragen Sie sich, ob es möglich ist, das Endergebnis mit weniger kostspieligen Stilen oder alternativen Methoden zu erreichen.

Sie möchten das Zeichnen so weit wie möglich vermeiden, insbesondere bei Animationseffekten. Denn das Zeitbudget von 10 Millisekunden pro Frame reicht in der Regel nicht aus, um die Zeichenarbeit abzuschließen, insbesondere auf mobilen Geräten.

Das obige ist der detaillierte Inhalt vonOptimierung der Browser-Rendering-Leistung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage