Optimiser les performances du frontend. Partie 2. Boucle d'événement, mise en page, peinture, composite

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. "1" ? ?



    function loop() {
    Promise.resolve().then(loop);   
    }
    setTimeout(() => {console.log(1)}, 0);
    loop();


  2. , , cursor: pointer :hover CSS , :hover background-color c . :



    while (true);


    : ? ? ?



  3. 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 ?

:



  1. <script>
  2. : setTimeout, setInterval, requestIdleCallback
  3. XmlHttpRequest, fetch ..
  4. API: click, mousedown, input, blur, visibilitychange, message , . ( , - ..).
  5. . , JS
  6. , : DOMMutationObserver, IntersectionObserver
  7. RequestAnimationFrame
  8. - ? :)


WebAPI ( API). :



  1. setTimeout(function a(){}, 100)
  2. WebAPI 100
  3. 100, WebAPI function a() (TaskQueue)
  4. 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 , .



. :



  1. :
  2. : , , ..


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 . :



  1. raf : DOMHighResTimeStamp — . perfomance.now,



  2. setTimeout, raf (id), raf cancelAnimationFrame.



  3. , — . Raf



  4. JS , , , requestAnimationFrame



  5. , ? :



    const checkRequestAnimationDiff = () => {
    let prev;
    function call() {
        requestAnimationFrame((timestamp) => {
            if (prev) {
                console.log(timestamp - prev); //     16.6 ,  60FPS
            }
            prev = timestamp;
            call();
        });
    }
    call();
    }
    checkRequestAnimationDiff();


    , ( hh.ru):





  6. () 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 :



  1. (offsetWidth, offsetLeft, getBoundingClientRect, ..)
  2. , , , 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:



  1. DOM
  2. force layout


Paint





, color, background .. :





, , . .



, , — Composition.



Composition





, - GPU. CSS , transform.



: .



: transform: translate . transform: translateZ(0) " ", .



GPU. .





transform . :



  1. transform layout ,
  2. "" , left, right, top, bottom


, transform , . .



?



( ) — layout. layout hh.ru. DOM, , 13-20 . .



:





Layout, , ..





layout paint, transform .



, :



  1. CSS. JS
  2. transform “”
  3. will-change — , "" . — , . , .
  4. DOM
  5. requestAnimationFrame
  6. \ . , layout.
  7. , . , , .




Runtime , . :



  1. ,


event loop :






All Articles