Os gerenciadores de entrada são uma possível causa de problemas de desempenho nos aplicativos, já que podem bloquear a conclusão de frames e causar mais trabalhos de layout desnecessários.
Os gerenciadores de entrada são uma possível causa de problemas de desempenho nos apps, porque podem bloquear a conclusão de frames e causar mais trabalho de layout desnecessário.
Resumo
- Evite gerenciadores de entrada de longa duração; eles podem bloquear a rolagem.
- Não faça mudanças de estilo nos gerenciadores de entrada.
- Rejeite os manipuladores; armazene valores de evento e trate as mudanças de estilo no próximo retorno de chamada de requestAnimationFrame.
Evite gerenciadores de entrada de longa duração
No caso mais rápido possível, quando um usuário interage com a página, a linha de execução do compositor da página pode pegar a entrada de toque do usuário e simplesmente mover o conteúdo. Isso não exige trabalho do encadeamento principal, onde são feitos JavaScript, layout, estilos ou pintura.
No entanto, se você anexar um gerenciador de entrada, como touchstart
, touchmove
ou touchend
, a linha de execução do compositor precisará esperar que esse gerenciador termine a execução, porque é possível optar por chamar preventDefault()
e interromper a rolagem por toque. Mesmo que você não chame preventDefault()
, o compositor precisa esperar e, assim, a rolagem do usuário é bloqueada, o que pode resultar em renderização lenta e frames perdidos.
Resumindo, você precisa garantir que todos os gerenciadores de entrada sejam executados rapidamente e que o compositor faça o trabalho.
Evitar mudanças de estilo em gerenciadores de entrada
Gerenciadores de entrada, como os de rolagem e toque, são programados para execução pouco antes de qualquer callback requestAnimationFrame
.
Se você fizer uma mudança visual dentro de um desses gerenciadores, haverá mudanças de estilo pendentes no início do requestAnimationFrame
. Se você então ler as propriedades visuais no início do callback requestAnimationFrame, como sugere o artigo Evite layouts grandes e complexos e a troca frequente de layouts, você acionará um layout síncrono forçado.
Retorne os gerenciadores de rolagem
A solução para os dois problemas acima é a mesma: retarde sempre as mudanças visuais para o próximo callback requestAnimationFrame
:
function onScroll (evt) {
// Store the scroll value for laterz.
lastScrollY = window.scrollY;
// Prevent multiple rAF callbacks.
if (scheduledAnimationFrame)
return;
scheduledAnimationFrame = true;
requestAnimationFrame(readAndUpdatePage);
}
window.addEventListener('scroll', onScroll);
Isso também tem o benefício adicional de manter os gerenciadores de entrada leves, o que é incrível porque agora você não está bloqueando coisas como rolagem ou toque em código de alto custo computacional.