Nuit. Un coup à la porte. Ouvert. Il y en a deux. "Croyez-vous en la boucle Event, notre principale chaîne de navigateurs?" Respirez. Ferme la porte. Allongez-vous pour faire le plein. Il reste encore 4 heures avant le début de la journée de travail. Et il y a déjà un événement de boucles, de layouts et autres joies ...
Dans la première partie, nous avons parlé du premier chargement et de l'utilisation des ressources. Aujourd'hui, je vais parler de la deuxième partie de l'optimisation des performances frontales. À propos de ce qui arrive à notre page lorsqu'elle est chargée, du temps processeur dépensé et de ce qu'il faut en faire. Mots-clés: boucle d'événement, peinture \ repeindre, mise en page \ redistribution, composite.
La cravate. Questions d'auto-test
Si vous souhaitez commencer à absorber le contenu de l'article tout de suite, ignorez cette section.
La boucle d'événements est populaire non seulement dans le travail quotidien, mais également dans les interviews. Et allez voir où il est le plus populaire. Il y a trois questions à vous poser pour vérifier si vous comprenez ce mécanisme de navigateur. Deux d'entre eux sont des habitués des entretiens, mais le troisième montre une compréhension de la boucle événementielle pour leur pratique. Ils sont assez simples, mais ils seront classés par ordre croissant de difficulté:
"1" ? ?
function loop() { Promise.resolve().then(loop); } setTimeout(() => {console.log(1)}, 0); loop();
, ,
cursor: pointer
:hover
CSS ,:hover
background-color
c . :
while (true);
: ? ? ?
height 0 auto? c JS / CSS. , , stackoverflow . event loop ,
height = auto
JS.
:
,
Event Loop
. :
while (true) {
if (execQueue.isNotEmpty()) {
execQueue.pop().exec();
}
}
100%. windows. . , , .
. , - , , . :
- .
: , JS ?
:
-
<script>
- :
setTimeout
,setInterval
,requestIdleCallback
-
XmlHttpRequest
,fetch
.. - API:
click
,mousedown
,input
,blur
,visibilitychange
,message
, . ( , - ..). - . , JS
- , :
DOMMutationObserver
,IntersectionObserver
RequestAnimationFrame
- - ? :)
WebAPI ( API). :
-
setTimeout(function a(){}, 100)
- WebAPI 100
- 100, WebAPI
function a()
(TaskQueue) - Event Loop
JS - DOM. , , - . .
. 2 , JS, CSS . , . JS, (, ..) . Event Loop JS "". render queue:
, . JS , . , SomeJSTasks .
JS 2 :
- TaskQueue — , .. Task
- MicroTaskQueue — MutationObserver. : MicroTask
Event loop . JS , .
. :
- :
- : , , ..
60FPS. . 60FPS, , .
Event Loop , 16.6 ( 60FPS)
TaskQueue
Task, event loop . , .. render queue , .., .
:
3 TaskA, TaskB, TaskC. Event Loop . 4 . Event Loop (Microtask queue render queue) — . EventLoop . 12 . 16 . Render queue , Event Loop . 1 . Event Loop TaskQueue.
Event Loop , . , , , , JS . : JS , , .
:
. 240 , 60FPS 16.6 . , 14 . , event loop render queue, . : , 14 , 15 .
, , :
— , , , .
:
function findJinny() {
debugger;
console.log('It seems you get confused with universe');
}
function goToTheCave() {
findJinny();
}
function becomeAPrince() {
goToTheCave();
}
function findAFriend() {
// ¯\_(ツ)_/¯
}
function startDndGame() {
const friends = [];
while (friends.length < 2) {
friends.push(findAFriend());
}
becomeAPrince();
}
console.log(startDndGame());
. ?
inline
, . , . inline
. startDndGame
, findAFriend
. callStack
, findAFriend
. :
?
. promise, mutationObserver. , TaskQueue.
: , .
, :
fulfilled rejected promise, , .
JS , . , , . : , . . :
4 MicrotaskQueue, , .
— . , MutationObserver — , , mutation observer . , , .
, event loop:
, , RenderQueue ( ).
RenderQueue?
. ( Layout):
:
RequestAnimationFrame (raf)
, - /. - .
DOM . :
raf :
DOMHighResTimeStamp
— .perfomance.now
,
setTimeout
, raf (id
), rafcancelAnimationFrame
.
, — . Raf
JS , , ,
requestAnimationFrame
, ? :
const checkRequestAnimationDiff = () => { let prev; function call() { requestAnimationFrame((timestamp) => { if (prev) { console.log(timestamp - prev); // 16.6 , 60FPS } prev = timestamp; call(); }); } call(); } checkRequestAnimationDiff();
, ( hh.ru):
() raf , . : https://github.com/whatwg/html/issues/2569#issuecomment-332150901
Style (recalculation)
, - , JS. media queries
a.styles.left = '10px'
, CSS , element.classList.add('my-styles-class')
CSSOM Render tree.
hh.ru, , Style:
Layout
, , , . DOM , .
layout -. , , Layout update layer tree
layout shift
, .
— Layout hh.ru .
Layout — -. , style recalculation , Layout :
- (offsetWidth, offsetLeft, getBoundingClientRect, ..)
- , , ,
transform
will-change
.transform
composition
,will-change
composition
. .
Layout :
Layout ( raf Style) , , , JS . force layout
. , JS Layout.
div1.style.height = "200px"; //
var height1 = div1.clientHeight; //
clientHeight div1 . , JS () : Style ( , ), Layout ( , ). Layout , , div1. , . . Layout Shift
. ( , Layout):
layout . , :
div1.style.height = "200px";
var height1 = div1.clientHeight; // <-- layout 1
div2.style.margin = "300px";
var height2 = div2.clientHeight; // <-- layout 2
div1 200px, . layout. . , layout . .
:
div1.style.height = "200px";
div2.style.margin = "300px";
var height1 = div1.clientHeight; // <-- layout 1
var height2 = div2.clientHeight;
layout, .
Layout "" . , chrome devtools -> More tools -> layers:
, event loop , tasks, microtasks force layout:
layout:
- DOM
- force layout
Paint
, color, background .. :
, , . .
, , — Composition.
Composition
, - GPU. CSS , transform.
: .
: transform: translate
. transform: translateZ(0)
" ", .
transform . :
- transform layout ,
- "" , left, right, top, bottom
, transform
, . .
?
( ) — layout. layout hh.ru. DOM, , 13-20 . .
:
Layout, , ..
layout paint, transform .
, :
- CSS. JS
-
transform
“” -
will-change
— , "" . — , . , . - DOM
-
requestAnimationFrame
- \ . , layout.
- , . , , .
Runtime , . :
- ,
event loop :