违规长时间运行的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:

  1. 切掉一些可能不必要的任务
  2. 找出如何更快地完成相同的任务
  3. 将代码分成多个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.offsetLeftelem.offsetTopelem.offsetWidthelem.offsetHeightelem.offsetParent
  • elem.clientLeftelem.clientTopelem.clientWidthelem.clientHeight
  • elem.getClientRects()elem.getBoundingClientRect()

滚动的东西

  • elem.scrollBy()elem.scrollTo()
  • elem.scrollIntoView()elem.scrollIntoViewIfNeeded()
  • elem.scrollWidthelem.scrollHeight
  • elem.scrollLeftelem.scrollTop也设置它们

焦点

  • elem.focus()可以触发双重强制布局( 源 )

也…

  • elem.computedRoleelem.computedName
  • elem.innerText ( 来源 )

的getComputedStyle

window.getComputedStyle()通常会强制样式recalc( 源 )

window.getComputedStyle()也会强制布局,如果满足以下任何一个条件:

  1. 元素在阴影树中
  2. 有媒体查询(视口相关的)。 具体而言,以下之一:( 源 )* min-widthmin-heightmax-widthmax-heightwidthheight * aspect-ratiomin-aspect-ratiomax-aspect-ratio
    • device-pixel-ratioresolutionorientation
  3. 所要求的财产是以下之一:( 来源 )
    • heightwidth * toprightbottomleft * margin [ -left topright , – bottomleft -left简写 ]只有边缘是固定的。 *只有填充是固定的, padding [ -top-right-bottom-left简写 ]。 * transformtransform-originperspective-origin * translaterotatescale * webkit-filterbackdrop-filter * motion-pathmotion-offsetmotion-rotation * xyrxry

窗口

  • window.scrollXwindow.scrollY
  • window.innerHeightwindow.innerWidth
  • window.getMatchedCSSRules()只强制样式

forms

  • inputElem.focus()
  • inputElem.select()textareaElem.select() ( source )

鼠标事件

  • mouseEvt.layerXmouseEvt.layerYmouseEvt.offsetXmouseEvt.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 }); 

插入这个特技代码后,所有的警告信息都消失了。