Noite. Uma batida na porta. Abrir. Existem dois em pé. "Você acredita no loop de eventos, nossa principal rede de navegadores?" Respire. Feche a porta. Deite-se para encher. Faltam ainda 4 horas para o início da jornada de trabalho. E já existe um evento de loops, layouts e outras alegrias ...
Na primeira parte, falamos sobre primeiro carregar e trabalhar com recursos. Hoje vou falar sobre a segunda parte da otimização do desempenho do front-end. Sobre o que acontece com nossa página quando ela é carregada, quanto tempo de CPU é gasto e o que fazer com ele. Palavras-chave: loop de evento, pintura \ repintar, layout \ refluxo, composto.
A gravata. Perguntas de autoteste
Se você quiser começar a absorver o conteúdo do artigo imediatamente, pule esta seção.
O loop de eventos é popular não apenas no trabalho diário, mas também em entrevistas. E descubra onde é mais popular. Há três perguntas a se fazer para verificar se você entende esse mecanismo do navegador. Dois deles frequentam entrevistas regulares, mas o terceiro mostra uma compreensão do ciclo de eventos de sua prática. Eles são bastante simples, mas serão organizados em ordem crescente de dificuldade:
"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 :