Maison  >  Article  >  interface Web  >  Optimisation des performances de rendu du navigateur

Optimisation des performances de rendu du navigateur

巴扎黑
巴扎黑original
2017-06-26 11:53:491834parcourir

Performances de rendu

Les pages doivent non seulement se charger rapidement, mais aussi être fluides ; le défilement doit être aussi rapide qu'un simple glissement de doigt, et les animations et les interactions doivent être aussi fluides que de la soie.

60 ips et taux de rafraîchissement de l'appareil

Actuellement, le taux de rafraîchissement de l'écran de la plupart des appareils est de 60 fois/ secondes. Par conséquent, s'il y a une animation ou un effet de dégradé dans la page, ou si l'utilisateur fait défiler la page, la vitesse à laquelle le navigateur restitue chaque image de l'animation ou de la page doit être cohérente avec la fréquence de rafraîchissement de l'écran de l'appareil.

Le temps prévu pour chaque image est d'un peu plus de 16 millisecondes (1 seconde / 60 = 16,66 millisecondes). Mais en réalité, le navigateur a du travail de rangement à faire, donc tout le travail doit être effectué en 10 millisecondes . Si ce budget ne peut pas être respecté, les fréquences d'images chuteront et le contenu aura des saccades à l'écran. Ce phénomène est souvent appelé jank (jank) et aura un impact négatif sur l'expérience utilisateur.

Le pipeline de pixels

Il y a cinq domaines principaux à connaître et auxquels vous devez prêter attention pendant que vous travaillez. Ce sont les parties qui ont le plus de contrôle et qui sont des points clés dans le pipeline pixel-à-écran :

  • JavaScript. De manière générale, JavaScript est utilisé pour réaliser certains changements visuels. Par exemple, utilisez la fonction animer de jQuery pour créer une animation, trier un ensemble de données ou ajouter des éléments DOM à la page. En plus de JavaScript, il existe d'autres méthodes courantes pour réaliser des changements visuels, telles que les animations CSS, les transitions et l'API d'animation Web.

  • Calculs de styleCalculs de style. Il s'agit du processus permettant de déterminer quelles règles CSS s'appliquent à quels éléments en fonction des sélecteurs correspondants, par exemple .headline ou .nav > À partir de là, une fois les règles connues, elles sont appliquées et les styles finaux pour chaque élément. sont calculés.

  • mise en page. Après avoir connu quelles règles s'appliquent à un élément, le navigateur peut commencer à calculer l'espace qu'il occupera et sa position sur l'écran. Le mode de mise en page d'une page Web signifie qu'un élément peut affecter d'autres éléments. Par exemple, la largeur de l'élément affecte généralement la largeur de ses éléments enfants et de ses nœuds partout dans l'arborescence. le processus se produit fréquemment.

  • Dessinez . Le dessin est le processus de remplissage des pixels. Cela implique de dessiner du texte, des couleurs, des images, des bordures et des ombres, y compris chaque partie visible d'un élément. Le dessin est généralement effectué sur plusieurs surfaces (souvent appelées calques).

  • Synthétiser. Étant donné que des parties de la page peuvent être dessinées sur plusieurs calques, elles doivent être dessinées à l'écran dans le bon ordre pour que la page s'affiche correctement. Ceci est particulièrement important pour les éléments qui chevauchent un autre élément, car une erreur pourrait entraîner l’apparition incorrecte d’un élément au-dessus d’un autre.

Chaque partie du pipeline a une chance de provoquer un décalage, il est donc important de savoir exactement quelles parties du pipeline votre code déclenche.

Toutes les images ne passeront pas toujours par chaque partie du pipeline. En fait, que vous utilisiez JavaScript, CSS ou une animation Web, lors de la mise en œuvre de modifications visuelles, il existe généralement trois façons d'exécuter le pipeline pour une image spécifiée :

1. > Dessiner > Synthèse

Si vous modifiez l'attribut "layout" d'un élément, c'est-à-dire changez les propriétés géométriques de l'élément (telles que la largeur, la hauteur, etc.), le navigateur devra alors vérifier tous les autres éléments puis "redistribuer la page" automatiquement. Toutes les pièces affectées devront être repeintes et les éléments peints finaux devront être composés.

2. JS / CSS > Style > Dessin > Compositing

Si vous modifiez l'attribut "peinture uniquement" (comme l'image d'arrière-plan, couleur ou ombre du texte, etc.), c'est-à-dire les propriétés qui n'affectent pas la mise en page de la page, le navigateur ignorera la mise en page mais effectuera quand même le dessin.

3. JS/CSS > Styles > Composition

Si vous modifiez une propriété qui ne nécessite ni relayage ni repeinture, le navigateur effectuera uniquement la composition. effectué. Cette dernière approche entraîne le moins de surcharge et est la mieux adaptée aux points les plus sollicités du cycle de vie de l'application, tels que les animations ou le défilement.

La performance est l'art d'éviter l'exécution et de rendre toute opération effectuée la plus efficace possible. Dans de nombreux cas, cela nécessite de travailler avec le navigateur, et non contre lui. Il convient de garder à l’esprit que les différentes tâches de pipeline répertoriées ci-dessus varient en termes de surcharge de calcul, certaines tâches étant plus coûteuses que d’autres !

Optimiser l'exécution de JavaScript

JavaScript déclenche souvent des changements visuels. Parfois, cela est directement dû à des manipulations de style, et parfois, ce sont des calculs qui entraînent des changements visuels, comme la recherche ou le tri de données. peut être une cause fréquente de problèmes de performances et vous devez essayer de réduire son impact autant que possible.

L'analyse des performances JavaScript peut être considérée comme un art, car le code JavaScript que vous écrivez n'a rien à voir avec le code qui est réellement exécuté. Les navigateurs modernes utilisent des compilateurs JIT et diverses optimisations et astuces pour obtenir l'exécution la plus rapide possible, ce qui modifie considérablement la nature dynamique du code.

Quelques éléments pour aider votre application à bien exécuter JavaScript :

  • Pour les effets d'animation, évitez d'utiliser setTimeout ou setInterval, utilisez requestAnimationFrame.

  • Déplacez le JavaScript de longue durée du thread principal vers un Web Worker.

  • Utilisez de petites tâches pour effectuer des modifications DOM sur plusieurs images.

  • Utilisez la chronologie et le profileur JavaScript de Chrome DevTools pour évaluer l'impact de JavaScript.

Utilisez requestAnimationFrame pour réaliser des changements visuels

Lorsque l'écran subit des changements visuels, il est préférable d'effectuer des opérations au début du cadre . La seule façon de garantir que JavaScript s'exécute au début d'une image est d'utiliser 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);

Un framework ou un exemple peut utiliser setTimeout ou setInterval pour effectuer des modifications visuelles telles qu'une animation, mais le problème avec cette approche est que la fonction de rappel est appelée à un certain moment dans le cadre La course peut se situer juste à la fin du cadre, ce qui nous amène souvent à perdre des images, provoquant un décalage. (L'exécution de js tels que composite prend du temps et bloquera les mises à jour de l'interface utilisateur).

En fait, le comportement d'animation par défaut actuel de jQuery consiste à utiliser setTimeout. Il est fortement recommandé de patcher pour utiliser requestAnimationFrame !

Réduisez la complexité ou utilisez un Web Worker

JavaScript s'exécute sur le fil principal du navigateur, avec les calculs de style, la mise en page et, dans de nombreux cas, le dessin. Si JavaScript s'exécute trop longtemps, il bloque ce autre travail, provoquant potentiellement des pertes d'images.

Alors, soyez intelligent quant au moment où votre JavaScript s'exécute et pendant combien de temps. Par exemple, si vous effectuez une animation comme le défilement, il est préférable de trouver un moyen de maintenir le JavaScript dans la plage de 3-4 ms. Tout ce qui dépasse cela peut prendre trop de temps. Si vous êtes libre, vous n'avez pas à vous soucier autant du temps.

Dans de nombreux cas, il est possible de déplacer un travail de calcul pur vers un Web Worker, par exemple qui ne nécessite pas d'accès au DOM, de manipulation ou de parcours de données (comme le tri ou la recherche), ce qui tend à être un bon choix pour ce modèle, chargement et modélisation Il en va de même pour la génération.

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...});

Tous les jobs ne sont pas adaptés à ce modèle : les Web Workers n'ont pas d'accès au DOM. Si l'opération doit être effectuée sur le thread principal, envisagez une approche par lots qui divise la tâche volumineuse en tâches plus petites, chacune ne prenant pas plus de quelques millisecondes et s'exécutant dans le gestionnaire requestAnimationFrame pour chaque image.

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);
}

Cette approche a des conséquences UX et UI, vous devrez utiliser un indicateur de progression ou d'activité pour vous assurer que l'utilisateur sait que la tâche est en cours de traitement. En aucun cas, cette méthode ne bloque le thread principal de l'application, ce qui permet au thread principal de toujours répondre rapidement à l'interaction de l'utilisateur.

Découvrez la « taxe cadre » de JavaScript

Lors de l'évaluation d'un framework, d'une bibliothèque ou de votre propre code, veillez à évaluer la surcharge liée à l'exécution du code JavaScript image par image. Ceci est particulièrement important lors de l'exécution de travaux d'animation critiques en termes de performances, tels que des transformations ou des défilements.

La meilleure façon de mesurer la surcharge et les performances de JavaScript est d'utiliser Chrome DevTools. En règle générale, vous obtiendrez un enregistrement simple comme celui-ci :

La section principale fournit un diagramme en flammes des appels JavaScript afin que vous puissiez analyser exactement quelles fonctions ont été appelées et combien de temps chacune pris.

Si vous trouvez du JavaScript de longue durée, vous pouvez activer l'analyseur JavaScript en haut de l'interface utilisateur de DevTools :


Dans de cette façon, le profilage de JavaScript entraîne une surcharge, alors assurez-vous de l'activer uniquement si vous souhaitez une compréhension plus approfondie des fonctionnalités d'exécution de JavaScript. Avec cette case à cocher activée, vous pouvez maintenant faire la même chose et vous obtiendrez plus d'informations sur les fonctions appelées en JavaScript :

Avec ces informations, vous pouvez évaluer l'impact de JavaScript sur les performances des applications et commencer à identifier et corriger les points chauds où les fonctions prennent trop de temps à s'exécuter. Comme mentionné précédemment, vous devriez essayer de supprimer le JavaScript de longue durée ou, si cela n'est pas possible, le déplacer vers un Web Worker, libérant ainsi le thread principal pour continuer à effectuer d'autres tâches.

Évitez la micro-optimisation de JavaScript

Cela pourrait être sympa de savoir que le navigateur exécute une version d'une fonction 100 fois plus rapidement qu'une autre, comme demander le offsetTop de un élément que le calcul de getBoundingClientRect () est rapide, mais le nombre de fois que vous appelez une telle fonction par image est presque toujours très faible. Par conséquent, se concentrer sur cet aspect des performances JavaScript est souvent un effort inutile. Vous ne gagnez généralement que quelques dixièmes de millisecondes.

Si vous développez un jeu ou une application coûteuse en termes de calcul, vous pourriez être une exception à ce guide, car vous intégrerez généralement de nombreux calculs dans un seul cadre, auquel cas diverses méthodes sont très utiles.

En bref, utilisez les micro-optimisations avec prudence, car elles ne correspondent souvent pas au type d'application que vous créez. Selon la règle des 2/8, commencez par optimiser au niveau du goulot d'étranglement.

Réduire la portée et la complexité des calculs de style

La modification du DOM en ajoutant et en supprimant des éléments, en modifiant les attributs, les classes ou via des animations entraînera le redémarrage du navigateur Calcule les styles d'éléments et, dans de nombreux cas, également la mise en page (c'est-à-dire la redistribution automatique) de la page ou d'une partie de page. Ce processus est appelé style calculé calcul.

La première partie du calcul d'un style consiste à créer un ensemble de sélecteurs correspondants. Il s'agit essentiellement du navigateur qui détermine les classes, les pseudo-sélecteurs et les identifiants à appliquer à un élément donné.

La deuxième partie consiste à obtenir toutes les règles de style du sélecteur correspondant et à déterminer le style final pour cet élément. Dans Blink (le moteur de rendu pour Chrome et Opera), la surcharge de ces processus est à peu près la même, du moins pour l'instant :

Environ 50 % du temps utilisé pour calculer le style calculé pour un élément est utilisé pour faire correspondre les sélecteurs, tandis que l'autre moitié du temps est utilisée pour créer un RenderStyle (représentation de style calculé) à partir des règles de correspondance.

  • Réduisez la complexité des sélecteurs ; utilisez une approche centrée sur les classes telle que la spécification BEM (Block-Element_Modifer).

  • Réduit le nombre d'éléments dont les styles doivent être calculés.

Réduire la complexité du sélecteur

Dans le cas le plus simple, il n'existe qu'une seule classe d'éléments en CSS :

.title {
/* styles */
}

Cependant, comme le le projet grandit, des CSS plus complexes peuvent être produits et le sélecteur final peut ressembler à ceci :

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

Afin de savoir si un style doit être appliqué, le navigateur doit en fait demander "Est-ce un élément avec un titre de classe dont le parent est exactement le Nième enfant négatif plus 1 Éléments with class box?" Le calcul de ce résultat peut prendre un temps important, en fonction du sélecteur utilisé et du navigateur correspondant. Un sélecteur spécifique peut être modifié en classe :

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

Les développeurs peuvent avoir des problèmes avec le nom de la classe, mais le travail est beaucoup plus simple pour les navigateurs. Dans la version précédente, afin de savoir si l'élément était le dernier de son type, le navigateur devait d'abord tout savoir sur les autres éléments, et si les éléments qui le suivaient seraient le Nième dernier enfant, ce qui était plus rapide que de simplement faire correspondre les sélecteurs de classe vers les éléments sont beaucoup plus chers.

Lors de la génération de l'arbre de rendu, pour chaque élément DOM, le sélecteur correspondant doit être trouvé dans toutes les règles de style et les règles de style correspondantes doivent être fusionnées.
Le sélecteur CSS est analysé de droite à gauche, de sorte que le style commun soit sur le nœud parent de l'arborescence CSSOM, et le style plus spécifique (le sélecteur est plus spécifique) sera sur le nœud enfant, et le nœud les branches et les temps de parcours changeront peu. Si vous utilisez la méthode de gauche à droite pour lire les règles CSS, alors la plupart des règles ne correspondent pas jusqu'à la fin, et beaucoup de travail inutile sera effectué en utilisant la méthode de droite à gauche ; tant que vous constatez que le sélecteur le plus à droite ne correspond pas. S'il y a une correspondance, supprimez-la directement pour éviter de nombreuses correspondances invalides.

Réduire le nombre d'éléments pour lesquels les styles sont calculés

Une autre considération de performances, la quantité de travail qui doit être calculée lorsqu'un élément change est un facteur plus important pour de nombreuses mises à jour de style.

En termes généraux, le coût le plus défavorable du calcul du style calculé de elements est le nombre d'éléments multiplié par le nombre de sélecteurs, car chaque élément doit être vérifié au moins une fois par rapport à chaque règle de style pour voir si cela correspond.

Remarque : Cela était vrai : si vous modifiiez une classe sur (par exemple) l'élément body, tous les éléments enfants de la page devraient recalculer leurs styles calculés. Maintenant, c'est un peu différent : pour les éléments dont les styles sont recalculés lorsqu'ils sont modifiés, certains navigateurs maintiennent un petit ensemble de règles uniques à chacun de ces éléments. Cela signifie qu'en fonction de la position de l'élément dans l'arborescence et des propriétés spécifiques modifiées, l'élément ne doit pas nécessairement être recalculé.

Les calculs de style peuvent souvent être dirigés vers un petit nombre d'éléments cibles plutôt que d'invalider la page entière. Dans les navigateurs modernes, cela pose souvent moins de problèmes, car les navigateurs n'ont pas nécessairement besoin de vérifier tous les éléments qu'une modification peut affecter. En revanche, les navigateurs plus anciens ne sont pas nécessairement optimisés pour de telles tâches. Le nombre d'éléments déclarés invalides doit être réduit au maximum.

Remarque : Si vous aimez les composants Web, il convient de noter que les calculs de style sont légèrement différents à cet égard, car par défaut, les styles ne dépassent pas les limites du Shadow DOM et sont limités à un seul composant. au lieu de L'arbre entier. Cependant, dans l’ensemble, le même concept s’applique toujours : les petits arbres avec des règles simples seront traités plus efficacement que les grands arbres avec des règles plus complexes.

Mesurer le coût du recalcul de style

Le moyen le plus simple et le meilleur de mesurer le recalcul de style consiste à utiliser le mode Timeline de Chrome DevTools. Tout d’abord, ouvrez DevTools, accédez à l’onglet Chronologie, cochez Enregistrement et interagissez avec votre site Web. Après avoir arrêté l'enregistrement, vous verrez la situation illustrée dans la figure ci-dessous.

La barre en haut représente les images par seconde, si vous voyez la barre dépasser la ligne inférieure, la ligne 60fps, il y a de longues images en cours d'exécution.


Si certaines interactions comme le défilement ou d'autres interactions ont des images de longue durée, cela doit être examiné plus en détail.

Si un gros bloc violet apparaît, comme dans l'exemple ci-dessus, cliquez sur Enregistrer pour plus de détails.

Dans cette analyse, il y a un événement de style de recalcul de longue durée qui prend un peu plus de 18 millisecondes et se produit à Pendant le défilement, l'utilisateur éprouve une gigue notable.

Si vous cliquez sur l'événement lui-même, vous verrez une pile d'appels identifiant le point dans votre JavaScript qui a provoqué le déclenchement du changement de style. De plus, vous obtenez le nombre d'éléments dont les styles sont affectés par la modification (un peu plus de 400 éléments dans ce cas) et le temps nécessaire pour effectuer les calculs de style. Vous pouvez utiliser ces informations pour commencer à essayer de trouver des points de correction dans votre code.

Utiliser la spécification BEM

L'approche de codage de

BEM intègre en fait les avantages en termes de performances de la correspondance des sélecteurs mentionnés ci-dessus, car elle suggère une classe unique pour tous les éléments et intègre également le nom de la classe lorsqu'une hiérarchie est requise :

.list { }
.list__list-item { }

Si vous avez besoin de modificateurs, comme ci-dessus, nous voulons faire quelque chose de spécial pour le dernier élément enfant, vous pouvez l'ajouter comme suit :

.list__list-item--last-child {}

Si vous cherchez un bon moyen d'organiser votre CSS, BEM est vraiment un excellent point de départ, non seulement d'un point de vue structurel, mais aussi parce que la recherche de style est simplifiée.

Évitez les mises en page volumineuses et complexes et les instabilités de mise en page.

La mise en page est le processus par lequel le navigateur calcule les informations géométriques de chaque élément : sa taille et sa position sur la page. Chaque élément aura des informations de taille explicites ou implicites en fonction du CSS utilisé, du contenu de l'élément ou de son élément parent. Ce processus est appelé Mise en page dans Chrome, Opera, Safari et Internet Explorer. Cela s'appelle la redistribution automatique (Reflow) dans Firefox, mais le processus est en réalité le même.

Semblables aux calculs de style, les considérations directes concernant les frais généraux de mise en page sont les suivantes :

  1. Le nombre d'éléments qui doivent être disposés.

  2. La complexité de ces mises en page.

  • La portée de la mise en page est généralement l'ensemble du document.

  • Le nombre d'éléments DOM affectera les performances et le déclenchement de la disposition doit être évité autant que possible.

  • Évaluez les performances des modèles de mise en page ; les nouvelles versions de Flexbox sont plus rapides que les anciennes versions de Flexbox ou les modèles de mise en page basés sur des flotteurs.

  • Évitez les mises en page synchrones forcées et les turbulences de mise en page ; lisez les valeurs de style puis apportez des modifications de style.

Évitez autant que possible les opérations de mise en page

Lors du changement de style, le navigateur vérifie si le les modifications nécessitent une présentation des calculs et si l'arborescence de rendu doit être mise à jour. Les modifications apportées aux "propriétés géométriques " (telles que la largeur, la hauteur, la gauche ou le haut) nécessitent toutes des calculs de mise en page.

.box {
largeur : 20px;
hauteur : 20px;
}
/**Changement la largeur et la hauteur déclenchent la disposition. */
.box--expanded {
largeur : 200px ;
hauteur : 350px;
}

La mise en page s'applique presque toujours à l'ensemble du document. S'il y a un grand nombre d'éléments, il faudra beaucoup de temps pour déterminer les positions et les tailles de tous les éléments.

Si la mise en page ne peut être évitée, la clé est d'utiliser Chrome DevTools pour voir combien de temps prend la mise en page et déterminer si la mise en page est la cause du goulot d'étranglement. Tout d'abord, ouvrez DevTools, sélectionnez l'onglet « Chronologie », cliquez sur le bouton « Enregistrer » et interagissez avec votre site Web. Lorsque vous arrêtez l'enregistrement, vous verrez une analyse détaillée des performances de votre site :

En regardant attentivement le cadre dans l'exemple ci-dessus, nous voyons que plus de 20 des millisecondes sont consacrées à la mise en page Lorsque nous définissons 16 millisecondes dans l'animation pour afficher les images à l'écran, cette mise en page prend trop de temps. Vous pouvez également voir que DevTools indiquera la taille de l'arborescence (1618 éléments dans ce cas) et le nombre de nœuds à disposer.

Utilisez Flexbox au lieu des anciens modèles de mise en page

Les pages Web ont différents modèles de mise en page, certains plus largement pris en charge que d'autres. Les premiers modèles de mise en page CSS nous ont donné la possibilité de positionner les éléments sur l'écran de manière relative, absolue ou via des éléments flottants.

La capture d'écran ci-dessous montre la configuration générale de l'utilisation de flotteurs sur 1 300 boîtes. Bien entendu, il s’agit d’un exemple artificiel, car la plupart des applications utiliseront divers moyens pour positionner les éléments.

Si nous mettons à jour cet exemple pour utiliser Flexbox (le nouveau modèle de la plateforme web), une situation différente se produit :

Désormais, pour le même nombre d'éléments et le même aspect visuel, la mise en page prend beaucoup moins de temps (respectivement 3,5 ms contre 14 ms dans ce cas). Il est important de se rappeler que dans certains cas, Flexbox peut ne pas être une option car il n'est pas aussi pris en charge que les flottants, mais lorsque cela est possible, il faut au moins étudier l'impact des modèles de mise en page sur les performances du site Web et adopter un modèle qui minimise la surcharge d'exécution de la page Internet.

Dans tous les cas, que vous choisissiez Flexbox ou non, vous devez essayer d'éviter du tout de déclencher des mises en page lors des points de stress élevés de votre application !

Éviter la synchronisation forcée des mises en page

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

 

首先 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 快速确定绘制瓶颈

Vous pouvez utiliser Chrome DevTools pour déterminer rapidement la zone que vous dessinez. Ouvrez DevTools et appuyez sur la touche Échap de votre clavier. Dans le panneau qui apparaît, allez dans l'onglet "rendu" et cochez "Afficher les rectangles de peinture".

Lorsque cette option est activée, Chrome fera clignoter l'écran en vert à chaque fois qu'un dessin se produit. Si vous voyez tout l’écran clignoter en vert ou si vous voyez des zones de l’écran qui ne devraient pas être dessinées, vous devez approfondir vos recherches.

Il existe une option dans la chronologie de Chrome DevTools qui fournit plus d'informations : Draw Profiler. Pour activer cette option, accédez à Timeline et cochez la case "Paint" en haut. À noter, veillez à activer cette option uniquement lorsque vous essayez d'analyser des problèmes de dessin, car elle entraîne une surcharge et peut affecter les résultats de profilage. Idéalement utilisé lorsque vous souhaitez mieux comprendre ce qui est exactement dessiné.

Après avoir terminé les paramètres ci-dessus, vous pouvez maintenant exécuter l'enregistrement de la chronologie et l'enregistrement du dessin contiendra plus de détails. En cliquant sur l'enregistrement de tirage d'une image, vous entrerez dans l'analyseur de tirage pour cette image :

Cliquer sur l'analyseur de tirage fera apparaître une vue où vous pourrez visualiser les éléments qui ont été tirés, le temps qu'il faut et les appels de tirage individuels requis :

Ce profileur montre la zone et la complexité (en fait le temps qu'il faut pour dessiner) si éviter le tirage n'est pas une option , qui sont tous deux des aspects qui peuvent être corrigés.

Favorise les éléments déplacés ou estompés

Le dessin n'est pas toujours dessiné sur une seule image en mémoire. En fait, le navigateur peut dessiner sur plusieurs images ou calques de composition si nécessaire.

L'avantage de cette méthode est que les éléments qui sont régulièrement redessinés ou qui se déplacent sur l'écran grâce à des transformations peuvent être traités sans affecter les autres éléments. Il en va de même pour les fichiers artistiques comme Sketch, GIMP ou Photoshop, où des calques individuels peuvent être traités et composés les uns sur les autres pour créer l'image finale.

La meilleure façon de créer un nouveau calque est d'utiliser la propriété CSS will-change. Cette méthode fonctionne sur Chrome, Opera et Firefox, et créera une nouvelle couche de composition avec la valeur de transform :

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

Pour les navigateurs qui ne prennent pas en charge will-change mais bénéficient de la création de calques, comme Safari et Mobile Safari, vous devez utiliser la transformation 3D pour forcer la création d'un nouveau calque :

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

Mais attention : ne créez pas trop de couches, car chaque couche nécessite de la mémoire et une surcharge de gestion.

Si vous avez promu un élément vers une nouvelle couche, utilisez DevTools pour confirmer que cela a entraîné des avantages en termes de performances. Ne faites pas la promotion d’éléments sans les analyser.

Réduire la zone de dessin

Cependant, parfois, même si un élément est soulevé, un travail de dessin est quand même nécessaire. Un grand défi avec les problèmes de dessin est que le navigateur joint deux zones qui doivent être dessinées, ce qui peut entraîner le redessin de la totalité de l'écran. Ainsi, si vous avez un en-tête fixe en haut de la page et des éléments dessinés en bas de l'écran, l'écran entier peut finir par être redessiné.

Réduire la zone de dessin consiste souvent à disposer les animations et les transformations pour qu'elles ne se chevauchent pas trop, ou à essayer d'éviter d'animer certaines parties de la page.

Réduire la complexité des dessins

Quand il s'agit de dessiner, certains dessins sont plus chers que d'autres. Par exemple, dessiner un élément impliquant du flou (comme une ombre) prendra plus de temps que (par exemple) dessiner une boîte rouge. Cependant, cela n'est pas toujours évident avec CSS : background: red et box-shadow : 0, 4px, 4px, rgba(0,0,0,0.5); ne semble pas nécessairement avoir des caractéristiques de performances complètement différentes, mais c'est le cas.

À l'aide de l'analyseur de peinture ci-dessus, vous pouvez déterminer si vous devez rechercher d'autres moyens d'obtenir l'effet. Demandez-vous s'il est possible d'obtenir le résultat final en utilisant un ensemble de styles moins coûteux ou des méthodes alternatives.

Vous souhaitez éviter de dessiner autant que possible, notamment dans les effets d'animation. Car le budget temps de 10 millisecondes par image n'est généralement pas suffisant pour terminer le travail de dessin, notamment sur les appareils mobiles.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn