Violation tâche JavaScript longue durée a pris xx ms
Récemment, j'ai reçu ce genre d'avertissement, et c'est la première fois que je l'obtiens:
[Violation] Long running JavaScript task took 234ms
[Violation] Forced reflow while executing JavaScript took 45ms
Je travaille sur un projet de groupe et je n'ai aucune idée d'où ça vient. ce n'est jamais arrivé avant. Soudain, il apparaît quand quelqu'un d'autre impliqué dans le projet. Comment puis-je trouver quel fichier/fonction provoque un tel avertissement? J'ai cherché une réponse, mais surtout sur la solution sur la façon de le résoudre. Je ne peux pas le résoudre si Je ne trouve même pas la source du problème.
Notes: dans ce cas l'avertissement apparaît uniquement sur chrome. J'ai essayé D'utiliser Edge, Je n'ai pas reçu d'avertissements similaires. Je ne l'ai pas encore testé sur mozilla.
Mise à jour :
Je reçois même l'erreur de jquery.min.js
en disant:
[Violation] Handler took 231ms of runtime (50ms allowed) jquery.min.js:2
11 réponses
Mise à jour: Chrome 58+ A CACHÉ ces messages et d'autres messages de débogage par défaut. Pour les afficher, cliquez sur la flèche à côté de 'Info' et sélectionnez 'Verbose'.
Mise à jour 2: Chrome 57 activé "masquer les violations" par défaut. Pour les réactiver, vous devez activer les filtres et décocher la case "Masquer les violations".
Soudain, il apparaît quand quelqu'un d'autre impliqué dans le projet
Je pense qu'il est plus probable que vous avez mis à jour Chrome 56. Cet avertissement est un (omi) merveilleuse nouvelle fonctionnalité - veuillez l'éteindre uniquement si vous êtes désespéré et que votre évaluateur vous enlèvera des marques. Les problèmes sous-jacents sont là dans les autres navigateurs, mais les navigateurs ne vous disent tout simplement pas qu'il y a un problème. Le ticket Chromium est ici mais il n'y a pas vraiment de discussion intéressante à ce sujet: https://bugs.chromium.org/p/chromium/issues/detail?id=662497
Ces messages sont des avertissements au lieu d'erreurs car cela ne va pas vraiment causer de problèmes majeurs problème. Cela peut entraîner la chute des images ou une expérience moins fluide.
Ils valent la peine d'être étudiés et réparés pour améliorer la qualité de votre application. La façon de le faire est de prêter attention aux circonstances dans lesquelles les messages apparaissent, et de faire des tests de performance pour affiner où le problème se produit. Le moyen le plus simple de commencer les tests de performance est d'insérer du code comme ceci:
function someMethodIThinkMightBeSlow() {
const startTime = performance.now();
// Do the normal stuff for this function
const duration = performance.now() - startTime;
console.log(`someMethodIThinkMightBeSlow took ${duration}ms`);
}
Si vous voulez être plus avancé, vous pouvez également utiliser le profileur de Chrome: https://developers.google.com/web/tools/chrome-devtools/rendering-tools/
Ou utiliser une bibliothèque de benchmarking comme celle-ci: https://benchmarkjs.com/
Une fois que vous avez trouvé du code qui prend beaucoup de temps (50ms est le seuil de Chrome), vous avez quelques options:
- découpez une partie/la totalité de cette tâche qui peut être inutile
- comprendre comment faire la même tâche plus rapide
- divisez le code en plusieurs étapes asynchrones
(1) et (2) peuvent être difficiles ou impossibles. Mais parfois vraiment facile et devrait être vos premières tentatives. Si nécessaire, il devrait toujours être possible de le faire (3). Pour ce faire, vous utiliserez quelque chose comme
setTimeout(functionToRunVerySoonButNotNow);
Ou
// This one is not available natively in IE, but there are polyfills available.
Promise.resolve().then(functionToRunVerySoonButNotNow);
, Vous pouvez en savoir plus sur la nature asynchrone de javascript ici:
Http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-explained/
Ce ne sont que des avertissements comme tout le monde l'a mentionné. Cependant, si vous souhaitez les résoudre (ce que vous devriez faire), vous devez d'abord identifier la cause de l'avertissement. Il n'y a pas de raison unique pour laquelle vous pouvez obtenir un avertissement de refusion de force.
Quelqu'un a créé une liste pour certaines options possibles. Vous pouvez suivre la discussion pour plus d'informations.
Voici l'essentiel des raisons possibles -
Ce qui force la mise en page / refusion
Tous les ci-dessous les propriétés ou les méthodes, lorsque demandé / appelé JavaScript, déclenchera le navigateur pour calculer de manière synchrone le style et mise en page*. Ceci est également appelé refusion ou mise en page raclée , et est un goulot d'étranglement de performance commun.
Élément
Boîte métriquesFaites défiler les choses
elem.offsetLeft
,elem.offsetTop
,elem.offsetWidth
,elem.offsetHeight
,elem.offsetParent
elem.clientLeft
,elem.clientTop
,elem.clientWidth
,elem.clientHeight
elem.getClientRects()
,elem.getBoundingClientRect()
Concentrer
elem.scrollBy()
,elem.scrollTo()
elem.scrollIntoView()
,elem.scrollIntoViewIfNeeded()
elem.scrollWidth
,elem.scrollHeight
elem.scrollLeft
,elem.scrollTop
en outre, en les définissantÉgalement…
elem.focus()
peut déclencher unedouble Mise en page forcée (source )
elem.computedRole
,elem.computedName
elem.innerText
(source)GetComputedStyle
window.getComputedStyle()
forcera généralement le style recalc (source)
window.getComputedStyle()
forcera la mise en page, ainsi, si l'un des ce qui suit est vrai:
- L'élément est dans un arbre d'ombre
- Il existe des requêtes multimédia (liées à la fenêtre d'affichage). Plus précisément, l'une des opérations suivantes: (source) *
min-width
,min-height
,max-width
,max-height
,width
,height
*aspect-ratio
,min-aspect-ratio
,max-aspect-ratio
device-pixel-ratio
,resolution
,orientation
- la propriété demandée est l'une des suivantes: (source )
height
,width
*top
,right
,bottom
,left
*margin
[-top
,-right
,-bottom
,-left
, ou abréviation] seulement si le la marge est fixée. *padding
[-top
,-right
,-bottom
,-left
, ou raccourci ] seulement si le remplissage est fixe. *transform
,transform-origin
,perspective-origin
*translate
,rotate
,scale
*webkit-filter
,backdrop-filter
*motion-path
,motion-offset
,motion-rotation
*x
,y
,rx
,ry
Fenêtre
window.scrollX
,window.scrollY
window.innerHeight
,window.innerWidth
- {[72] } force uniquement le style
Formulaires
inputElem.focus()
inputElem.select()
,textareaElem.select()
(source)Événements de la Souris
mouseEvt.layerX
,mouseEvt.layerY
,mouseEvt.offsetX
,mouseEvt.offsetY
(source)Document
- {[80] } force uniquement le style
Plage
range.getClientRects()
,range.getBoundingClientRect()
SVG
- beaucoup; n'ont pas fait une liste exhaustive , mais la mise en page 2011 de Tony Gentilcore déclenche Liste a souligné quelques-uns.
Contenteditable
- Beaucoup et beaucoup de choses, ...y compris la copie d'une image dans le presse-papiers (source)
Vérifiez plus ici .
Mise à Jour:
Robocat à partir d'observations
Plus de fond: Le chrome le code source du problème original et une discussion sur une API de performance pour les Avertissements.
Quelques idées:
-
Supprimez la moitié de votre code (peut - être en le commentant).
Le problème Est toujours là? SUPER, vous avez réduit les possibilités! Répéter.
Le problème n'est-il pas là? OK, regardez la moitié que vous avez commentée!
Utilisez-vous un système de contrôle de version (par exemple, Git)? Si c'est le cas, {[0] } certains de vos commits les plus récents. Quand le problème introduit? Regardez le commit pour voir exactement quel code a changé lorsque le problème est arrivé.
Regardez dans la console Chrome sous L'onglet Réseau et trouvez les scripts qui prennent le plus de temps à charger.
Dans mon cas, il y avait un jeu Angulaire ajouter les scripts que j'avais compris, mais pas encore utilisé dans l'application :
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.8/angular-ui-router.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-utils/0.1.1/angular-ui-utils.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular-animate.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular-aria.min.js"></script>
Ce sont les seuls fichiers JavaScript qui ont pris plus de temps à charger que le temps spécifié par l'erreur "tâche longue durée".
Tous ces fichiers s'exécutent sur mes autres sites Web sans aucune erreur générée mais je recevais cette erreur" tâche longue durée" sur une nouvelle application web qui avait à peine toutes les fonctionnalités. L'erreur s'est arrêtée immédiatement après la suppression.
Ma meilleure supposition est que ces add-ons angulaires cherchaient récursivement dans des sections de plus en plus profondes du DOM pour leurs balises de départ-n'en trouvant aucune, ils ont dû traverser L'ensemble du DOM avant de quitter, ce qui a pris plus de temps que Chrome attend-donc l'avertissement.
Cela pourrait provenir de Chrome 56 beta si vous l'utilisez.
, Mais il n'est pas sur le changelog: https://blog.chromium.org/2016/12/chrome-56-beta-not-secure-warning-web.html
Vous pouvez le masquer dans la barre de filtre de la console avec la case à cocherMasquer les violations .
1 est arrivé à la Console
2 Cliquez sur l'icône de filtre près (case à cocher" Journal de conservation")
3 Cochez La Case "Masquer La Violation"
Modifier
Cette fonctionnalité est supprimée de Chrome 58
Modifiez la liste déroulante du niveau de journalisation sur Verbose pour voir les violations.
Dans mon cas, j'ai découvert que c'était en fait causé par Adblock.
J'ai exécuté mon application et l'ai enregistrée dans onglet Performance {[2] } dans Chrome.
Là, vous pouvez vérifier diverses fonctions qui ont pris beaucoup de temps à exécuter. Celui qui corelated avec des avertissements dans la console provenait d'un fichier qui a été chargé par l'extension Adblock.
Vérifiez ces fichiers et essayez d'identifier s'il s'agit d'un code d'extensions ou du vôtre
J'ai trouvé une solution dans le code source D'Apache Cordova. Ils implémentent comme ceci:
var resolvedPromise = typeof Promise == 'undefined' ? null : Promise.resolve();
var nextTick = resolvedPromise ? function(fn) { resolvedPromise.then(fn); } : function(fn) { setTimeout(fn); };
Implémentation Simple, mais de manière intelligente.
Sur Android 4.4, utilisez Promise
.
Pour les navigateurs plus anciens, utilisez setTimeout()
Utilisation:
nextTick(function() {
// your code
});
Après avoir inséré ce code d'astuce, tous les messages d'avertissement ont disparu.
J'ai trouvé la racine de ce message dans mon code. Fonctionnalité: recherche qui masquent / afficher les nœuds (hors ligne). Était:
search.addEventListener('keyup', function() {
for (const node of nodes)
if (node.innerText.toLowerCase().includes(this.value.toLowerCase()))
node.classList.remove('hidden');
else
node.classList.add('hidden');
});
Dans l'onglet Performances (profileur):
Maintenant:
search.addEventListener('keyup', function() {
const nodesToHide = [];
const nodesToShow = [];
for (const node of nodes)
if (node.innerText.toLowerCase().includes(this.value.toLowerCase()))
nodesToShow.push(node);
else
nodesToHide.push(node);
nodesToHide.forEach(node => node.classList.add('hidden'));
nodesToShow.forEach(node => node.classList.remove('hidden'));
});
Dans l'onglet Performances (profileur):
Et je pense que maintenant la recherche fonctionne plus rapidement (229 nœuds).
Vous devez avoir un sélecteur de classe répété qui est recherché repeteatedly par javascript. Si quelque chose doit utiliser un id, utilisez - le comme id, pas comme une classe. Qui s'est vraiment passé pour moi.