违规长时间运行的JavaScript任务花费了xx ms
最近我得到了这样的警告,说实话这是我第一次得到这样的警告:
[Violation] Long running JavaScript task took 234ms [Violation] Forced reflow while executing JavaScript took 45ms
我正在做一个小组项目,我不知道它来自哪里。 这从来没有发生过。 突然出现当别人参与这个项目的时候。 我怎么find哪个文件/函数导致这样的警告? 我一直在寻找答案,但主要是关于如何解决它的解决scheme。 如果我找不到问题的根源,我无法解决。
注意:在这种情况下,警告只出现在chrome上。 我试图用Edge,没有得到任何类似的警告。 还没有在Mozilla上testing过。
更新:我甚至从jquery.min.js
得到的错误说:
[Violation] Handler took 231ms of runtime (50ms allowed) jquery.min.js:2
任何答案是非常赞赏。
更新:Chrome 58+默认隐藏了这些和其他debugging消息。 要显示它们,请单击“信息”旁边的箭头并select“详细”。
更新2:Chrome 57默认打开“隐藏违规”。 要重新打开它,您需要启用filter并取消选中“隐藏违规”框。
突然出现当别人参与这个项目的时候
我认为你更有可能更新到Chrome 56.这个警告是一个(IMO)奇妙的新function – 如果你绝望的话,请closures它,你的评估者会把你的痕迹从你身上移开。 其他浏览器中存在潜在的问题,但是浏览器并没有告诉你有什么问题。 铬票在这里,但没有任何有趣的讨论: https : //bugs.chromium.org/p/chromium/issues/detail?id = 662497
这些消息是警告而不是错误,因为这不是真的会导致重大问题。 这可能会导致帧丢失或导致不太顺畅的体验。
但值得研究和修复,以提高应用程序的质量。 做到这一点的方法是关注消息出现的情况,并进行性能testing以缩小问题发生的位置。 开始性能testing最简单的方法是插入一些如下所示的代码:
function someMethodIThinkMightBeSlow() { const startTime = performance.now(); // Do the normal stuff for this function const duration = performance.now() - startTime; console.log(`someMethodIThinkMightBeSlow took ${duration}ms`); }
如果您希望获得更高级的function,您还可以使用Chrome的分析器: https : //developers.google.com/web/tools/chrome-devtools/rendering-tools/
或者使用这样的基准库: https : //benchmarkjs.com/
一旦你发现一些需要很长时间的代码(50毫秒是Chrome的门槛),你有几个select:
- 切掉一些可能不必要的任务
- 找出如何更快地完成相同的任务
- 将代码分成多个asynchronous步骤
(1)和(2)可能是困难的或不可能的。 但有时候很容易,应该是你的第一次尝试。 如果需要,应该始终可以做(3)。 要做到这一点,你会使用类似的东西
setTimeout(functionToRunVerySoonButNotNow);
要么
// This one is not available natively in IE, but there are polyfills available. Promise.resolve().then(functionToRunVerySoonButNotNow);
你可以在这里阅读更多关于javascript的asynchronous特性:
http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-explained/
一些想法:
-
删除一半的代码(也许通过评论)。
-
问题仍然存在吗? 太棒了,你已经缩小了可能性! 重复。
-
问题不在吗? 好的,看看你注意到的一半!
-
-
你使用任何版本控制系统(例如,Git)? 如果是这样,
git checkout
一些你最近的提交。 问题何时出现? 看看提交问题,看看到底问题是什么时候改变的。
这些只是大家提到的警告。 但是,如果您热衷于解决这些问题(您应该这么做),那么您需要首先确定是什么导致了警告。 没有任何理由可以得到强制回stream警告。
有人为一些可能的选项创build了一个列表 。 您可以按照讨论了解更多信息。
这是可能原因的要点 –
什么力量布局/回stream
所有下面的属性或方法,当在JavaScript中被请求/调用时,将触发浏览器同步计算样式和布局*。 这也被称为回stream或布局颠簸 ,是常见的性能瓶颈。
元件
框指标
elem.offsetLeft
,elem.offsetTop
,elem.offsetWidth
,elem.offsetHeight
,elem.offsetParent
elem.clientLeft
,elem.clientTop
,elem.clientWidth
,elem.clientHeight
elem.getClientRects()
,elem.getBoundingClientRect()
滚动的东西
elem.scrollBy()
,elem.scrollTo()
elem.scrollIntoView()
,elem.scrollIntoViewIfNeeded()
elem.scrollWidth
,elem.scrollHeight
elem.scrollLeft
,elem.scrollTop
也设置它们焦点
elem.focus()
可以触发双重强制布局( 源 )也…
elem.computedRole
,elem.computedName
elem.innerText
( 来源 )的getComputedStyle
window.getComputedStyle()
通常会强制样式recalc( 源 )
window.getComputedStyle()
也会强制布局,如果满足以下任何一个条件:
- 元素在阴影树中
- 有媒体查询(视口相关的)。 具体而言,以下之一:( 源 )*
min-width
,min-height
,max-width
,max-height
,width
,height
*aspect-ratio
,min-aspect-ratio
,max-aspect-ratio
device-pixel-ratio
,resolution
,orientation
- 所要求的财产是以下之一:( 来源 )
height
,width
*top
,right
,bottom
,left
*margin
[-left
top
,right
, –bottom
,left
-left
或简写 ]只有边缘是固定的。 *只有填充是固定的,padding
[-top
,-right
,-bottom
,-left
或简写 ]。 *transform
,transform-origin
,perspective-origin
*translate
,rotate
,scale
*webkit-filter
,backdrop-filter
*motion-path
,motion-offset
,motion-rotation
*x
,y
,rx
,ry
窗口
window.scrollX
,window.scrollY
window.innerHeight
,window.innerWidth
window.getMatchedCSSRules()
只强制样式forms
inputElem.focus()
inputElem.select()
,textareaElem.select()
( source )鼠标事件
mouseEvt.layerX
,mouseEvt.layerY
,mouseEvt.offsetX
,mouseEvt.offsetY
( source )文件
doc.scrollingElement
只强制样式范围
range.getClientRects()
,range.getBoundingClientRect()
SVG
- 非常多; 还没有一个详尽的清单,但托尼Gentilcore的2011布局触发列表指出了一些。
CONTENTEDITABLE
- 很多东西,包括复制图像到剪贴板( 源 )
点击这里查看 。
1得到控制台
2单击附近的filter图标(“Preserv日志”checkbox)
3勾选“隐藏违规”checkbox
编辑
该function已从Chrome 58中删除
将日志logging级别下拉列表更改为“详细”以查看违规情况。
如果你使用的话,它可能来自Chrome 56 beta。
但是这并不在变更日志上: https : //blog.chromium.org/2016/12/chrome-56-beta-not-secure-warning-web.html
您可以将隐藏侵犯checkbox隐藏在控制台的filter栏中。
查看“networking”标签下的Chrome控制台,find最长时间加载的脚本。
在我的情况下,有一套Angular添加了我已经包含但尚未在应用中使用的脚本:
<script src="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>
这些是唯一加载的时间比“长时间运行”错误指定时间长的JavaScript文件。
所有这些文件运行在我的其他网站上,没有生成错误,但我刚刚得到这个“长时间运行任务”错误的一个新的Web应用程序,几乎没有任何function。 删除后立即停止错误。
我最好的猜测是,这些Angular附加函数recursion地查看DOM的越来越深的部分的开始标签 – 没有发现,它们必须在退出之前遍历整个DOM,这需要比Chrome期望的更长的时间 – 因此是警告。
就我而言,我发现这实际上是由Adblock造成的。
我运行我的应用程序,并将其logging在Chrome的“ 性能”选项卡中。
在那里你可以检查花费很长时间运行的各种function。 与控制台中的警告相关联的是来自Adblock扩展加载的文件。
检查这些文件,并尝试确定这是否是一些扩展代码或你的
如果你正在使用铬金丝雀,只需检查“隐藏违规”选项。 看这里
我想我明白Chrome / FF开发者试图告诉我们什么:一个网页应用程序或网站应该由一个空白页面组成,不要超过一个input栏,一个button,一个高度压缩的JPEG文件, 。 只要你没有真正使用它的大部分function,并且不要编写超过100行代码,而且在任何情况下都不允许开发人员直接访问任何DOM对象,事件处理程序和JavaScript所提供的一切(因为它干扰了框架)。 每个人都应该坚持Times New Roman,而不是用CSS来玩,因为上帝禁止,它可能会意外触发我们的浏览器一直在做的“回stream”。 如果遇到性能问题,可以通过添加尽可能多的其他框架/库来增加JavaScript的数量,这将帮助您在第一个框架中追踪鬼魂。 我们的浏览器(包括FF)没有什么问题 – 所有的性能问题都是您的错,我们已经做了额外的努力,每当我们想到您的代码时,都会在您的面前发出警告。
我在Apache Cordova源代码中find了一个解决scheme。 他们这样执行:
var resolvedPromise = typeof Promise == 'undefined' ? null : Promise.resolve(); var nextTick = resolvedPromise ? function(fn) { resolvedPromise.then(fn); } : function(fn) { setTimeout(fn); };
简单的实现,但聪明的方式。
在Android 4.4中,使用Promise
。 对于较老的浏览器,使用setTimeout()
用法:
nextTick(function() { // your code });
插入这个特技代码后,所有的警告信息都消失了。