Récemment, j'ai eu 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 ne sais pas d'où ça vient. Ce n'est jamais arrivé avant. Soudain, il est apparu que quelqu'un d'autre s'était impliqué dans le projet. Comment trouver quel fichier/quelle fonction provoque cet avertissement? Je cherchais la réponse, mais surtout la solution pour y remédier. Je ne peux pas le résoudre si je ne trouve même pas la source du problème.
Dans ce cas, l'avertissement apparaît uniquement sur Chrome. J'ai essayé d'utiliser Edge, mais je n'ai reçu aucun avertissement similaire, et je ne l'ai pas encore testé sur Firefox.
J'ai même l'erreur de jquery.min.js
:
[Violation] Handler took 231ms of runtime (50ms allowed) jquery.min.js:2
Mise à jour : Chrome 58+ a masqué 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".
Chrome 57 activait par défaut "masquer les violations". 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 ayez mis à jour Chrome 56. Cet avertissement est une nouveauté merveilleuse. À mon avis, désactivez-le uniquement si vous êtes désespéré et que votre évaluateur vous enlèvera des marques. Les problèmes sous-jacents existent dans les autres navigateurs, mais ceux-ci ne vous disent pas qu'il y a un problème. Le billet Chromium est ici mais il n’ya pas vraiment de discussion intéressante à ce sujet.
Ces messages sont des avertissements au lieu d'erreurs car ils ne vont pas vraiment causer de problèmes majeurs. Cela risquerait de faire tomber les images ou de rendre l’utilisation moins fluide.
Toutefois, ils valent la peine d’être étudiés et corrigés pour améliorer la qualité de votre application. Pour ce faire, il faut être attentif aux circonstances dans lesquelles les messages apparaissent et effectuer des tests de performances pour cerner le problème. Le moyen le plus simple de démarrer les tests de performance consiste à insérer du code comme celui-ci:
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 souhaitez être plus avancé, vous pouvez également utiliser le profileur de Chrome , ou utiliser une bibliothèque d'analyse comparative telle que celle-ci .
Une fois que vous avez trouvé du code qui prend beaucoup de temps (50 ms est le seuil de Chrome), vous avez plusieurs options:
(1) et (2) peuvent être difficiles ou impossibles, mais c'est parfois très facile et devraient ê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 .
Ce ne sont que des avertissements comme tout le monde l'a mentionné. Toutefois, si vous souhaitez résoudre ces problèmes (ce que vous devriez faire), vous devez d'abord identifier la cause de l'avertissement. Il n'y a pas une seule raison pour laquelle vous pouvez obtenir un avertissement de refusion forcée. 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:
Quelles forces layout/refusion
Toutes les propriétés ou méthodes ci-dessous, lorsqu'elles sont demandées/appelées en JavaScript, obligeront le navigateur à calculer simultanément le style et la mise en page *. Cela s'appelle également redistribution ou mise en page dynamique et constitue un goulot d'étranglement courant en termes de performances.
Élément
Boîte de mesuresFaites 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
également, les réglerAussi…
elem.focus()
peut déclencher une mise en page forcée double ( source )
elem.computedRole
,elem.computedName
elem.innerText
( source )getComputedStyle
window.getComputedStyle()
forcera généralement le style à recalculer ( source )
window.getComputedStyle()
forcera la disposition, si l'une des conditions suivantes est vraie:
- L'élément est dans un arbre d'ombre
- Il existe des requêtes de médias (liées à la fenêtre d'affichage). Plus précisément, l'un des éléments suivants: ( 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’un des suivants: ( source )
height
,width
*top
,right
,bottom
,left
*margin
[-top
,-right
,-bottom
,-left
, ou raccourci] uniquement si la marge est fixe. *padding
[-top
,-right
,-bottom
,-left
, ou en abrégé] uniquement si le remplissage est corrigé. *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
window.getMatchedCSSRules()
ne force que le styleFormes
inputElem.focus()
inputElem.select()
,textareaElem.select()
( source )Événements de souris
mouseEvt.layerX
,mouseEvt.layerY
,mouseEvt.offsetX
,mouseEvt.offsetY
( source )document
doc.scrollingElement
ne force que le styleGamme
range.getClientRects()
,range.getBoundingClientRect()
SVG
- Beaucoup; Nous n'avons pas fait de liste exhaustive, mais La liste de déclenchement de mise en page 2011 de Tony Gentilcore en a signalé quelques-unes.
contenteditable
- Beaucoup de choses,… y compris la copie d'une image dans le presse papier ( source )
Vérifiez plus ici .
En outre, voici le code source Chromium du version originale et un discussion sur une API de performance pour les avertissements.
Edit: Il existe également un article sur la façon de minimiser la redistribution de la présentation sur PageSpeed Insight de Google . Il explique ce qu'est le reflow du navigateur:
Redistribution est le nom du processus de navigateur Web permettant de recalculer les positions et les géométries des éléments du document afin de restituer tout ou partie du document. Le refusion étant une opération qui bloque l'utilisateur dans le navigateur, il est utile pour les développeurs de savoir comment améliorer le temps de refusion et de comprendre les effets de diverses propriétés de document (profondeur DOM, efficacité des règles CSS, différents types de changements de style) sur le refoulement. temps. Parfois, refondre un seul élément dans le document peut nécessiter de refondre ses éléments parents ainsi que tous les éléments qui le suivent.
En outre, il explique comment le minimiser:
- Réduisez les profondeurs de DOM inutiles. Les modifications apportées à un niveau de l'arborescence DOM peuvent entraîner des modifications à tous les niveaux de l'arborescence, de la racine à la racine, jusqu'aux enfants du nœud modifié. Cela conduit à plus de temps consacré à la refusion.
- Réduisez les règles CSS et supprimez les règles CSS inutilisées.
- Si vous apportez des modifications de rendu complexes telles que des animations, faites-le en dehors du flux. Utilisez position-absolute ou position-fixed pour accomplir cela.
- Évitez les sélecteurs CSS complexes et inutiles - les sélecteurs descendants en particulier - qui nécessitent davantage de puissance de calcul pour effectuer la correspondance de sélecteur.
Quelques idées:
Supprimez la moitié de votre code (peut-être en le commentant).
Le problème est-il toujours là? Génial, vous avez réduit les possibilités! Répéter.
Le problème n'est-il pas là? Ok, regarde la moitié que tu as commentée!
Utilisez-vous un système de contrôle de version (par exemple, Git)? Si tel est le cas, git checkout
certains de vos commits les plus récents. Quand le problème a-t-il été introduit? Regardez le commit pour voir exactement quel code a changé lorsque le problème est arrivé pour la première fois.
Dans mon cas, j'ai découvert que cela était en fait causé par un code provenant d'une extension. Pour moi, l'extension était AdBlock.
Pour identifier la source du problème, exécutez votre application et enregistrez-la dans onglet Performances de Chrome.
Vous pouvez y vérifier diverses fonctions qui ont pris beaucoup de temps. Dans mon cas, la corrélation avec les avertissements dans la console provenait d'un fichier chargé par l'extension AdBlock, mais cela pourrait être autre chose dans votre cas.
Vérifiez ces fichiers et essayez d’identifier s’il s’agit du code d’une extension ou du vôtre. (Si c'est le vôtre, alors vous avez trouvé la source de votre problème.)
Recherchez dans la console Chrome sous l'onglet Réseau et recherchez les scripts dont le chargement est le plus long.
Dans mon cas, il y avait un ensemble de Angular scripts additionnels que j'avais inclus mais que je n'avais pas encore utilisés 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>
Il s’agissait des seuls fichiers JavaScript dont le chargement a été plus long que le temps spécifié par l’erreur "Long Running Task".
Tous ces fichiers s’exécutent sur mes autres sites Web sans générer d’erreurs, mais j’obtenais cette erreur "Long Running Task" sur une nouvelle application Web qui ne comportait pratiquement aucune fonctionnalité. L'erreur s'est arrêtée immédiatement après la suppression.
Ma meilleure hypothèse est que ces additifs Angular cherchaient récursivement des sections de plus en plus profondes du DOM dans leurs balises de départ - sans en trouver, ils devaient parcourir l'intégralité du DOM avant de sortir, ce qui prenait plus de temps que Chrome attend - d'où l'avertissement.
Ceci a été ajouté dans la version bêta de Chrome 56, bien que cela ne figure pas dans ce journal des modifications du blog Chromium: avertissement "Non sécurisé" de Chrome 56, Web Bluetooth et CSS position: sticky
Vous pouvez masquer cela dans la barre de filtre de la console avec la case à cocher Masquer les violations .
J'ai trouvé la racine de ce message dans mon code, qui cherchait et masquait ou montrait des nœuds (hors ligne). C'était mon code:
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');
});
L'onglet Performances (profileur) indique que l'événement dure environ 60 ms:
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'));
});
L'onglet Performances (profileur) affiche maintenant l'événement qui dure environ 1 ms:
Et je pense que la recherche marche plus vite maintenant (229 nœuds).
Si vous utilisez Chrome Canary (ou bêta), cochez simplement l'option "Masquer les violations".
J'ai trouvé une solution dans le code source 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); };
Une mise en œuvre simple, mais intelligente.
Sur Android 4.4, utilisez Promise
. Pour les anciens navigateurs, utilisez setTimeout()
Usage:
nextTick(function() {
// your code
});
Après avoir inséré ce code astuce, tous les messages d’avertissement ont disparu.
Il s'agit d'une erreur de violation de Google Chrome qui s'affiche lorsque le niveau de journalisation Verbose
est activé.
Exemple de message d'erreur:
Explication:
Redistribution est le nom du processus de navigateur Web permettant de recalculer les positions et les géométries des éléments du document afin de restituer tout ou partie du document. Le refusion étant une opération qui bloque l'utilisateur dans le navigateur, il est utile pour les développeurs de savoir comment améliorer le temps de refusion et de comprendre les effets de diverses propriétés de document (profondeur DOM, efficacité des règles CSS, différents types de changements de style) sur le refoulement. temps. Parfois, refondre un seul élément dans le document peut nécessiter de refondre ses éléments parents ainsi que tous les éléments qui le suivent.
Article original: Réduire au minimum la redistribution du navigateur par Lindsey Simon, développeur UX, publiée sur developers.google.com.
Et c'est le lien Google Chrome vous donne dans le profileur de performances, sur les profils de présentation (les régions mauves), pour plus d'informations sur l'avertissement.
le refoulement forcé se produit souvent lorsque vous avez une fonction appelée plusieurs fois avant la fin de l'exécution.
Par exemple, vous pouvez avoir le problème sur un smartphone et non sur un navigateur classique.
Je suggère d'utiliser un setTimeout pour résoudre le problème.
Ce n’est pas très important, mais je le répète, le problème se pose lorsque vous appelez une fonction plusieurs fois, et non lorsque la fonction est supérieure à 50 ms. Je pense que vous vous trompez dans vos réponses.
1 arrivé à la console
2 Cliquez sur l'icône de filtre à proximité (case à cocher "Conserver le journal").
3 Cochez la case "Masquer la violation"
EDIT
Cette fonctionnalité a été supprimée de Chrome 58.
Modifiez le menu déroulant du niveau de journalisation sur Verbose pour voir les violations.