Cette nouvelle API JavaScript peut vous aider à éviter le compromis entre les performances de chargement et la réactivité des entrées.
Le chargement rapide est difficile. Les sites qui utilisent actuellement JavaScript pour afficher leur contenu qu'il faut trouver un compromis entre les performances de charge et l'entrée Réactivité: vous pouvez soit effectuer toutes les tâches requises pour l'affichage simultanément (meilleures performances de chargement, moins bonne réactivité aux entrées). diviser le travail en tâches plus petites afin de rester réactif à de saisie et de peinture (mauvaise performance de chargement, meilleure entrée la réactivité).
Pour éliminer ce compromis, Facebook a proposé et implémenté
l'API isInputPending()
dans Chromium afin d'améliorer la réactivité sans
et le rendement. Suite aux commentaires que nous avons reçus concernant la phase d'évaluation, nous avons modifié la
API, et nous avons le plaisir de vous annoncer qu'elle est désormais disponible par défaut dans Chromium.
87!
Compatibilité du navigateur
Navigateurs pris en charge
-
<ph type="x-smartling-placeholder">
-
<ph type="x-smartling-placeholder">
-
<ph type="x-smartling-placeholder">
-
<ph type="x-smartling-placeholder">
isInputPending()
expédiés dans les navigateurs basés sur Chromium à partir de la version 87.
Aucun autre navigateur n'a signalé d'intention d'expédier l'API.
Contexte
Dans l'écosystème JS actuel, la plupart des tâches sont effectuées sur un seul thread: le thread principal. Cela fournit un modèle d'exécution robuste aux développeurs, mais l'expérience utilisateur (réactivité en particulier) peuvent être considérablement affectés si le script s'exécute en temps réel. Si la page effectue beaucoup de travail lors du déclenchement d'un événement d'entrée, Par exemple, la page ne gérera l'événement de saisie de clic qu'après cette tâche terminé.
La bonne pratique actuelle consiste à résoudre ce problème en décomposant le code JavaScript en blocs plus petits. Pendant le chargement de la page, de code JavaScript, puis céder le contrôle et transmettre le contrôle au navigateur. La le navigateur peut alors vérifier sa file d'attente d'événements d'entrée et voir s'il y a dont il doit parler à la page. Le navigateur peut ensuite reprendre l'exécution des blocs JavaScript au fur et à mesure de leur ajout. Cela aide, mais cela peut causer d'autres problèmes.
Chaque fois que la page rend le contrôle au navigateur, un certain temps le navigateur doit vérifier sa file d'attente des événements d'entrée, traiter les événements et récupérer Bloc JavaScript. Même si le navigateur répond plus rapidement aux événements, le temps de chargement de la page ralentit. Si nous cédons trop souvent, la page charge trop lentement. Si le rendement est moindre, le navigateur met plus de temps répondre aux événements utilisateur, et les gens sont frustrés. Ce n'est pas amusant.
Chez Facebook, nous voulions voir à quoi ressemblerait si nous trouvions un
une nouvelle approche de chargement
qui éliminerait ce compromis frustrant. Mer
nous avons contacté nos amis de l'équipe Chrome
pour isInputPending()
. L'API isInputPending()
est la première à utiliser le concept de
interrompt les entrées utilisateur sur le Web et permet
vérifier les entrées sans
céder au navigateur.
Comme l'API avait suscité un intérêt, nous avons collaboré avec nos collègues de l'équipe Chrome pour implémenter et livrer la fonctionnalité dans Chromium. avec l'aide de Chrome ingénieurs, nous avons obtenu les correctifs après une évaluation de l'origine (qui permet à Chrome de tester les modifications et de recevoir les commentaires des développeurs) avant de publier complètement une API).
Nous avons pris en compte les commentaires de la phase d'évaluation et des autres membres W3C Web Performance Working Group et mis en œuvre des modifications à l'API.
Exemple: un planificateur plus rendement
Supposons que vous ayez une tâche de blocage d'affichage à effectuer pour charger votre
page, par exemple la génération d'un balisage à partir de composants, la décomposition de nombres premiers ou
il suffit de dessiner une
icône de chargement de chargement intéressante. Chacun de ces éléments est divisé en une
élément de travail. À l'aide du modèle de planificateur, esquissons
comment nous pourrions traiter
notre travail dans une fonction processWorkQueue()
hypothétique:
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();
}
En appelant processWorkQueue()
plus tard dans une nouvelle macrotâche via setTimeout()
, nous
permet au navigateur de rester réactif à la saisie (il peut
exécuter des gestionnaires d'événements avant la reprise du travail) tout en gérant l'exécution
sans interruption. Cependant, nous pourrions être déprogrammés
longtemps par d'autres travaux
qui souhaite contrôler la boucle d'événements ou obtenir jusqu'à QUANTUM
millisecondes supplémentaires
de latence des événements.
Ce n'est pas grave, mais pouvons-nous faire mieux ? Bien sûr !
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();
}
En appelant navigator.scheduling.isInputPending()
, nous pouvons :
répondre plus rapidement aux entrées, tout en veillant à ce que le blocage de l'affichage fonctionne
s’exécute sans interruption. Si nous ne souhaitons pas nous occuper
autre que la saisie (par exemple, peinture) jusqu'à ce que le travail soit terminé, nous pouvons facilement augmenter
la longueur de QUANTUM
également.
Par défaut,
« continu » Les événements ne sont pas renvoyés par isInputPending()
. Ces
incluent mousemove
, pointermove
et d'autres. Si vous souhaitez générer un rendement
sans problème. En fournissant un objet à isInputPending()
avec
includeContinuous
défini sur true
, le tour est joué:
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();
}
Et voilà ! Les frameworks comme React intègrent la prise en charge de isInputPending()
dans leur
les principales bibliothèques de planification
à l’aide d’une logique similaire. J’espère que cela vous
les développeurs qui utilisent ces frameworks peuvent bénéficier de isInputPending()
.
en coulisse sans avoir à les réécrire de façon significative.
Rendement n'est pas toujours mauvais
Notez que le rendement inférieur n'est pas la solution adaptée à chaque utilisation. . Il existe de nombreuses raisons de rendre le contrôle au navigateur, traiter les événements d'entrée, par exemple pour effectuer le rendu et exécuter d'autres scripts sur la page.
Il existe des cas où le navigateur n'est pas en mesure d'attribuer correctement les attributs en attente
des événements d'entrée. en particulier la définition d'extraits et de masques complexes pour plusieurs origines.
Les iFrames peuvent signaler des faux négatifs (par exemple, isInputPending()
peut renvoyer de façon inattendue
"false" lors du ciblage de ces frames). Assurez-vous de céder
suffisamment souvent si
votre site nécessite des interactions avec des sous-cadres stylisés.
Faites également attention aux autres pages qui partagent une boucle d'événements. Sur des plates-formes telles que
comme Chrome pour Android, il est assez courant que plusieurs origines partagent un événement
en boucle. isInputPending()
ne renvoie jamais true
si l'entrée est envoyée à un
les frames multi-origines. Par conséquent, les pages en arrière-plan peuvent interférer avec le
la réactivité des pages de premier plan. Vous voudrez peut-être réduire, repousser
plus souvent lorsqu'elles travaillent en arrière-plan à l'aide de l'API Page Visibility.
Nous vous encourageons à utiliser isInputPending()
avec discernement. S'il n'y a pas
de blocage des utilisateurs, puis soyez gentil avec les autres membres de la boucle d'événements en
et à générer plus fréquemment. Les longues tâches peuvent être dangereuses.
Commentaires
- Laissez un commentaire sur les spécifications dans le is-input-pending.
- Contactez @acomminos (l'un des auteurs de la spécification). sur Twitter.
Conclusion
Nous sommes heureux de vous annoncer le lancement de isInputPending()
et que les développeurs puissent
pour commencer à l'utiliser dès aujourd'hui. C'est la première fois que Facebook crée une API
nouvelle API Web et est passé de l'incubation d'idées à la proposition de normes pour
dans un navigateur. Nous tenons à remercier toutes les personnes qui nous ont aidés à en arriver là
et remercier toutes les personnes qui nous ont aidés à étoffer leur fiche
cette idée et de la faire livrer !
Photo principale prise par Will H McMahan sur Unsplash.