Le navigateur souhaite regrouper le calcul des styles et le travail de mise en page. Les problèmes de performance apparaissent lorsque le code de l'application interrompt constamment ce plan en alternant écritures et lectures du DOM dans des boucles serrées.
Ce motif est généralement appelé thrashing de mise en page.
Le Motif de Bugs
Voici la forme coûteuse :
for (const item of items) {
item.style.width = "200px";
const rect = item.getBoundingClientRect();
item.style.height = `${rect.width}px`;
}
Chaque appel à getBoundingClientRect() peut forcer le navigateur à vider le travail de mise en page en attente avant de pouvoir répondre. Si cela se produit pendant le défilement, le redimensionnement ou l'animation, l'interface utilisateur devient rapidement saccadée.
Meilleur Motif
Regroupez d'abord les lectures. Regroupez ensuite les écritures :
const widths = items.map((item) => item.getBoundingClientRect().width);
items.forEach((item, index) => {
item.style.width = "200px";
item.style.height = `${widths[index]}px`;
});
Ce n'est pas la seule solution possible, mais cela montre la règle sous-jacente : évitez de forcer le navigateur à recalculer en continu la mise en page à l'intérieur d'un code sensible aux trames.
Quand Cela a-t-il Réellement de l'Importance
Vous le ressentez généralement dans :
- les gestionnaires de défilement
- les boucles d'animation
- les interactions de glisser-déposer
- les grandes listes avec manipulation directe du DOM
Le navigateur est rapide lorsque vous le laissez regrouper le travail. Cela devient coûteux lorsque vous le contraignez à répondre immédiatement à des questions de géométrie après chaque écriture.
Si le code doit s'exécuter pendant une animation ou une interaction, requestAnimationFrame est souvent le bon endroit pour planifier le travail de DOM regroupé afin que les lectures et les écritures se produisent dans une limite de trame plus prévisible.
Lectures Supplémentaires