Uma nova API JavaScript que pode ajudar a evitar o equilíbrio entre desempenho de carregamento e capacidade de resposta de entrada.
Carregar rápido é difícil. Sites que usam JavaScript para renderizar conteúdo atualmente é preciso escolher entre o desempenho de carga e o responsividade: realize todo o trabalho necessário para exibir de uma só vez (melhor desempenho de carregamento, menor capacidade de resposta a entradas) ou dividir o trabalho em tarefas menores para permanecer responsivo entrada e gravação (pior desempenho de carregamento, melhor entrada capacidade de resposta).
Para eliminar essa necessidade, o Facebook propôs e implementou
a API isInputPending()
no Chromium para melhorar a capacidade de resposta sem
rendendo. Com base no feedback do teste de origem, fizemos várias atualizações na
API, e temos o prazer de anunciar que agora ela é disponibilizada por padrão no Chromium.
87!
Compatibilidade com navegadores
O isInputPending()
é enviado em navegadores baseados no Chromium a partir da versão 87.
Nenhum outro navegador sinalizou uma intenção de enviar a API.
Contexto
A maior parte do trabalho no ecossistema JS atual é feita em uma única linha de execução: a principal. Isso fornece um modelo de execução robusto para desenvolvedores, mas a experiência do usuário (em especial, a capacidade de resposta) podem sofrer drasticamente se o script for executado por um longo tempo de resposta. Se a página estiver fazendo muito trabalho enquanto um evento de entrada é acionado, por exemplo, a página não processará o evento de entrada de clique até que esse trabalho é concluída.
A prática recomendada atual é lidar com esse problema quebrando o o JavaScript em blocos menores. Enquanto a página é carregada, ela pode executar uma um pouco de JavaScript e depois gerar e passar o controle de volta para o navegador. A navegador poderá verificar a fila de eventos de entrada e conferir se há algo ele precisa informar à página. Em seguida, o navegador pode voltar a executar a O JavaScript bloqueia à medida que são adicionados. Isso ajuda, mas pode causar outros problemas.
Sempre que a página retorna o controle ao navegador, leva algum tempo o navegador para verificar a fila de eventos de entrada, processar eventos e selecionar os próximos bloco de JavaScript. O navegador responde aos eventos mais rapidamente, mas o o tempo de carregamento da página fica lento. E, se nos rendermos com muita frequência, a página carrega muito lentamente. Se a redução da frequência, o navegador demorará mais para reagem a eventos do usuário, e isso faz com que as pessoas fiquem frustradas. Nada divertido.
No Facebook, queríamos saber como seria se tivéssemos um
abordagem nova de carregamento que eliminaria essa escolha frustrante. Qa
entramos em contato com nossos amigos do Chrome
sobre isso e nos apresentou a proposta
para isInputPending()
. A API isInputPending()
é a primeira a usar o conceito de
interrompe entradas do usuário na Web e permite que o JavaScript seja
capazes de verificar entradas sem abrir mão do navegador.
Como houve interesse na API, fizemos uma parceria com nossos colegas do Chrome. para implementar e enviar o recurso no Chromium. Com a ajuda do Chrome para engenheiros, temos os patches aplicados em um teste de origem (uma forma de o Chrome testar as alterações e receber feedback dos desenvolvedores antes do lançamento completo de uma API).
Recebemos feedback do teste de origem e de outros membros da W3C Web Performance Working Group e implementaram mudanças na API.
Exemplo: um programador de rendimento
Vamos supor que você tenha que executar vários comandos de bloqueio de exibição para carregar
página, por exemplo, gerando marcações a partir de componentes, fatorando primos ou
um ícone de carregamento. Cada um deles é dividido em
item de trabalho. Usando o padrão do programador, vamos esboçar como processar
nosso trabalho em uma função processWorkQueue()
hipotética:
const DEADLINE = performance.now() + QUANTUM;
while (workQueue.length > 0) {
if (performance.now() >= DEADLINE) {
// Yield the event loop if we're out of time.
setTimeout(processWorkQueue);
return;
}
let job = workQueue.shift();
job.execute();
}
Invocando processWorkQueue()
mais tarde em uma nova macrotarefa usando setTimeout()
,
dar ao navegador a capacidade de permanecer um pouco responsivo a entradas (ele pode
executar manipuladores de eventos antes que o trabalho seja retomado) enquanto ainda consegue executar relativamente
sem interrupções. No entanto, outros trabalhos podem nos desviar por muito tempo
que queira controlar o loop de eventos ou consiga até QUANTUM
milissegundos extras
de latência de eventos.
Está tudo bem, mas podemos melhorar? Claro!
const DEADLINE = performance.now() + QUANTUM;
while (workQueue.length > 0) {
if (navigator.scheduling.isInputPending() || performance.now() >= DEADLINE) {
// Yield if we have to handle an input event, or we're out of time.
setTimeout(processWorkQueue);
return;
}
let job = workQueue.shift();
job.execute();
}
Ao introduzir uma chamada para navigator.scheduling.isInputPending()
, podemos
responder mais rapidamente às entradas, sem deixar de garantir que nosso trabalho de bloqueio
será executada sem interrupções. Se não estivermos interessados em lidar com nada
além da entrada (por exemplo, pintura) até que o trabalho esteja concluído, podemos aumentar
também o comprimento de QUANTUM
.
Por padrão, "contínuo" eventos não são retornados de isInputPending()
. Esses
incluem mousemove
, pointermove
, entre outros. Se você tiver interesse em gerar
sem problemas. Ao fornecer um objeto para isInputPending()
com
includeContinuous
definido como true
, pronto:
const DEADLINE = performance.now() + QUANTUM;
const options = { includeContinuous: true };
while (workQueue.length > 0) {
if (navigator.scheduling.isInputPending(options) || performance.now() >= DEADLINE) {
// Yield if we have to handle an input event (any of them!), or we're out of time.
setTimeout(processWorkQueue);
return;
}
let job = workQueue.shift();
job.execute();
}
Pronto! Frameworks como o React estão criando suporte para isInputPending()
nos próprios
as principais bibliotecas de programação usando uma lógica parecida. Espero que isso leve
desenvolvedores que usam esses frameworks para se beneficiar do isInputPending()
nos bastidores sem reescritas significativas.
Rendimento nem sempre é ruim
Vale ressaltar que produzir menos não é a solução certa para todos os usos. caso. Há muitas razões para retornar o controle ao navegador além de processar eventos de entrada, como a renderização e a execução de outros scripts da página.
Há casos em que o navegador não consegue atribuir os atributos pendentes
eventos de entrada. Especificamente, a configuração de clipes e máscaras complexos para origens cruzadas
Os iframes podem informar falsos negativos (ou seja, isInputPending()
pode retornar inesperadamente
false ao segmentar esses frames). Certifique-se de estar rendendo com frequência suficiente se
seu site exige interações com subframes estilizados.
Esteja atento a outras páginas que também compartilham um loop de eventos. Em plataformas como
como o Chrome para Android, é comum que várias origens compartilhem um evento
repetição. isInputPending()
nunca vai retornar true
se a entrada for enviada para um
de origem cruzada. Assim, as páginas em segundo plano podem interferir na
a capacidade de resposta
das páginas em primeiro plano. Talvez você queira reduzir, adiar ou produzir
com mais frequência ao trabalhar em segundo plano usando a API Page Visibility.
Recomendamos que você use o isInputPending()
com cautela. Se não houver
trabalho de bloqueio de usuários a ser feito e, em seguida, seja gentil com os outros no loop de eventos,
produzindo com mais frequência. Tarefas longas podem ser prejudiciais.
Feedback
- Deixe seu feedback sobre as especificações na repositório is-input-pending.
- Entre em contato com @acomminos (um dos autores das especificações). no Twitter.
Conclusão
Estamos felizes com o lançamento do isInputPending()
e que os desenvolvedores possam
para começar a usá-la hoje mesmo. Essa API é a primeira vez que o Facebook cria uma
a nova API da Web, da concepção da ideia à proposta de padrões,
envio em um navegador. Gostaríamos de agradecer a todos que nos ajudaram a alcançar esse
e agradecer a todos do Chrome que nos ajudaram a desenvolver
a ideia e enviá-la.
Foto hero de Will H McMahan no Abrir a página.