web-dev-qa-db-ja.com

違反長時間のJavaScriptタスクの実行に要した時間はxx ms

最近、私はこの種の警告を受けました、そしてこれは私が初めてそれを得た時です:

[Violation] Long running JavaScript task took 234ms
[Violation] Forced reflow while executing JavaScript took 45ms

私はグループプロジェクトに取り組んでいます、そしてそれがどこから来るのか私にはわかりません。これはかつてなかったことです。突然、他の誰かがプロジェクトに関わったときに現れます。どのファイル/関数がそのような警告を引き起こしているのかをどうやって見つけることができますか?私は答えを探していましたが、主にそれを解決する方法の解決策についてです。問題の原因が見つからないと解決できません。

注:この場合、警告はクロムにのみ表示されます。私はEdgeを使おうとしました、同様の警告を得ませんでした。私はまだmozillaでそれをテストしていません。

更新日:私はjquery.min.jsから言ってもエラーが出ます:

[Violation] Handler took 231ms of runtime (50ms allowed)            jquery.min.js:2
226
procatmer

更新:Chrome 58以降では、デフォルトでこれらおよびその他のデバッグメッセージが非表示になりました。それらを表示するには、「情報」の横にある矢印をクリックして「詳細」を選択します。

アップデート2:Chrome 57はデフォルトで '違反を隠す'をオンにした。それらを元に戻すには、フィルタを有効にして[違反を隠す]チェックボックスをオフにする必要があります。

他の誰かがプロジェクトに関わったときに突然現れます

Chrome 56にアップデートした方がいいと思います。この警告は(imo)素晴らしい新機能です。根本的な問題は他のブラウザにありますが、ブラウザはただ問題があると言っているのではありません。 Chromiumのチケットはここにありますが、実際には興味深い議論はありません。 https://bugs.chromium.org/p/chromium/issues/detail?id=662497

これらのメッセージは、実際には大きな問題を引き起こすことはないので、エラーではなく警告です。それはフレームを落としたりさもなければより滑らかでない経験を引き起こすかもしれません。

しかし、それらはあなたのアプリケーションの品質を改善するために調査し修正する価値があります。これを行う方法は、メッセージがどのような状況で表示されるかに注意を払い、問題が発生している場所を絞り込むためのパフォーマンステストを実行することです。パフォーマンステストを開始する最も簡単な方法は、次のようなコードを挿入することです。

function someMethodIThinkMightBeSlow() {
    const startTime = performance.now();

    // Do the normal stuff for this function

    const duration = performance.now() - startTime;
    console.log(`someMethodIThinkMightBeSlow took ${duration}ms`);
}

さらに高度になりたい場合は、Chromeのプロファイラを使用することもできます。 https://developers.google.com/web/tools/chrome-devtools/rendering-tools/

あるいは、次のようなベンチマークライブラリを利用してください。 https://benchmarkjs.com/ /

長い時間がかかるコード(50ミリ秒がChromeのしきい値)を見つけたら、いくつかの選択肢があります。

  1. 不要な場合があるそのタスクの一部または全部を切り取る
  2. 同じタスクをもっと速くする方法を見つけ出す
  3. コードを複数の非同期ステップに分割する

(1)と(2)は難しいか不可能です。しかし時には本当に簡単で、あなたの最初の試みであるべきです。必要ならば、それは常に可能であるべきです(3)。これをするためにあなたはのようなものを使うでしょう

setTimeout(functionToRunVerySoonButNotNow);

または

// This one is not available natively in IE, but there are polyfills available.
Promise.resolve().then(functionToRunVerySoonButNotNow);

あなたはここでJavaScriptの非同期性についてもっと読むことができます:

http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-explained/ /

203
voltrevo

誰もが言ったように、これらは単なる警告です。ただし、これらの解決に熱心な場合は(必要な場合)、最初に警告の原因を特定する必要があります。強制リフロー警告を取得できる理由は1つではありません。誰かがいくつかの可能なオプションに対して list を作成しました。詳細については、ディスカッションを参照してください。
考えられる理由の要点は次のとおりです。

レイアウト/リフローを強制するもの

JavaScriptで要求または呼び出されると、以下のプロパティまたはメソッドはすべて、ブラウザーをトリガーしてスタイルとレイアウトを同期的に計算します*。これはリフローまたは レイアウトスラッシング とも呼ばれ、一般的なパフォーマンスのボトルネックです。

素子

ボックスメトリック
  • 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()は、double強制レイアウトをトリガーできます(- source
また…
  • elem.computedRoleelem.computedName
  • elem.innerTextソース

getComputedStyle

window.getComputedStyle()は通常、スタイルの再計算を強制します( source

以下のいずれかに該当する場合、window.getComputedStyle()もレイアウトを強制します。

  1. 要素はシャドウツリーにあります
  2. メディアクエリ(ビューポート関連のクエリ)があります。具体的には、次のいずれか:( source )* min-widthmin-heightmax-widthmax-heightwidthheight * aspect-ratiomin-aspect-ratiomax-aspect-ratio
    • device-pixel-ratioresolutionorientation
  3. 要求されたプロパティは次のいずれかです:( source
    • heightwidth * toprightbottomleft * margin [-top-right-bottom-left、またはshorthand]は、マージンが固定されている場合のみ。 * padding [-top-right-bottom-left、またはshorthand)がパディングの場合のみ固定されています。 * transformtransform-Originperspective-Origin * translaterotatescale * webkit-filterbackdrop-filter * motion-pathmotion-offsetmotion-rotation * xyrxry

  • window.scrollXwindow.scrollY
  • window.innerHeightwindow.innerWidth
  • window.getMatchedCSSRules()はスタイルのみを強制します

フォーム

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

マウスイベント

  • mouseEvt.layerXmouseEvt.layerYmouseEvt.offsetXmouseEvt.offsetYsource

資料

  • doc.scrollingElementはスタイルのみを強制します

範囲

  • range.getClientRects()range.getBoundingClientRect()

SVG

コンテンツ編集可能

  • たくさんのもの、…クリップボードへの画像のコピーを含む( source

詳細を確認してください こちら

また、警告用の 元の問題 および パフォーマンスAPIに関する議論 のChromiumソースコードもあります。


編集:PageSpeed Insight by Google でレイアウトのリフローを最小限に抑える方法に関する記事もあります。ブラウザのリフローについて説明します。

リフローは、ドキュメントの一部またはすべてを再レンダリングする目的で、ドキュメント内の要素の位置とジオメトリを再計算するためのWebブラウザプロセスの名前です。リフローはブラウザでのユーザーのブロック操作であるため、開発者がリフロー時間を改善する方法を理解し、リフローに対するさまざまなドキュメントプロパティ(DOM深さ、CSSルールの効率、さまざまなタイプの変更)の影響を理解するのに役立ちます時間。文書内の単一の要素をリフローするには、その親要素とそれに続く要素もリフローする必要がある場合があります。

さらに、最小化する方法について説明します。

  1. 不要なDOMの深さを減らします。 DOMツリーの1つのレベルでの変更は、ツリーのすべてのレベルで変更を引き起こす可能性があります-ルートまで、変更されたノードの子までずっと。これにより、リフローの実行により多くの時間が費やされます。
  2. CSSルールを最小化し、未使用のCSSルールを削除します。
  3. アニメーションなどの複雑なレンダリングの変更を行う場合は、フロー外で行ってください。これを実現するには、位置絶対または位置固定を使用します。
  4. 不要な複雑なCSSセレクター、特に子孫セレクター-セレクターのマッチングを行うためにより多くのCPUパワーを必要とするものを避けてください。
67
noob

いくつかのアイデア:

  • あなたのコードの半分を削除してください(おそらくそれをコメントアウトすることによって)。

    • 問題はまだありますか?素晴らしい、あなたは可能性を絞り込んだのです!繰り返す。

    • 問題はありませんか?さて、あなたがコメントアウトした半分を見てください!

  • バージョン管理システム(Gitなど)を使用していますか?もしそうなら、最近のコミットのいくつかをgit checkout。問題はいつ発生しましたか。最初に問題が発生したときに変更されたコードを正確に確認するには、コミットを調べてください。

26
therobinkim

私の場合、これは実際には拡張機能(私の場合はAdblock)のコードが原因であることがわかりました。

問題の原因を特定するには、アプリケーションを実行してChromeの [パフォーマンス]タブ に記録します。

実行に時間がかかったさまざまな機能を確認できます。私の場合、コンソールの警告と関連したものはAdblock拡張子によってロードされたファイルからのものでしたが、これはあなたの場合他の何かかもしれません。

これらのファイルをチェックして、これがいくつかの拡張コードかあなたのものかを確認してください。

8
Matt Leonowicz

Chromeコンソールの[ネットワーク]タブで、読み込みに最も時間がかかるスクリプトを見つけます。

私の場合は、私が含めたがまだアプリで使用されていないスクリプトにAngular addのセットがありました。

<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>

これらは、 "Long Running Task"エラーで指定された時間よりもロードに時間がかかった唯一のJavaScriptファイルです。

これらのファイルはすべて他のWebサイトでもエラーなしで実行されますが、機能がほとんどない新しいWebアプリケーションではこの "Long Running Task"エラーが発生しました。削除するとすぐにエラーが停止しました。

私の推測では、これらのAngularアドオンは、開始タグについてDOMのますます深いセクションを再帰的に調べていました。したがって警告です。

5
Jordan Reddick

あなたがそれを使用すればそれはChrome 56ベータ版からかもしれません。

しかし、それはchangelogにありません: https://blog.chromium.org/2016/12/chrome-56-beta-not-secure-warning-web.html

違反を非表示にする チェックボックスを使用して、コンソールのフィルタバーでこれを非表示にすることができます。

4
Bastien

私は自分のコードでこのメッセージの根本を見つけました。機能性:ノードを非表示/表示する検索(オフライン)。でした:

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');
});

[パフォーマンス]タブ(プロファイラ)の場合: Chromium performance profiler layour recalculation reflow

今:

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'));
});

[パフォーマンス]タブ(プロファイラ)の場合: Chromium profiler dark

そして私は今検索がより速く働くと感じます(229ノード)。

3

あなたがクロムカナリアを使用しているのであれば、単に 'hide violations'オプションをチェックしてください。 ここを見てください

3
zhaoming

私はApache Cordovaのソースコードに解決策を見つけました。彼らはこのように実装します。

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
});

このトリックコードを挿入した後、すべての警告メッセージは消えます。

3
wf9a5m75

これはGoogle Chromeの違反エラーで、Verboseのログレベルが有効になっているときに表示されます。

エラーメッセージの例:

screenshot of the warning 

説明:

Reflowは、ドキュメントの一部または全部を再レンダリングする目的で、ドキュメント内の要素の位置とジオメトリを再計算するためのWebブラウザプロセスの名前です。リフローはブラウザでのユーザーブロック操作なので、リフロー時間を短縮する方法を理解し、さまざまなドキュメントプロパティ(DOMの深さ、CSSルールの効率、さまざまな種類のスタイル変更)がリフローに与える影響を理解する時間。文書内の1つの要素をリフローすると、その親要素とそれに続く要素もリフローする必要がある場合があります。

元の記事: ブラウザのリフローを最小限に抑える UX開発者のLindsey Simon著、developers.google.comに投稿。

そして これはリンクです 警告の詳細については、Google ChromeのPerformanceプロファイラーのレイアウトプロファイル(藤色の領域)を参照してください。

0
brokenthorn

実行が終了する前に関数が複数回呼び出されると、強制リフローがよく発生します。

たとえば、あなたはスマートフォンではなく古典的なブラウザでは問題を抱えているかもしれません。

この問題を解決するためにsetTimeoutを使用することをお勧めします。

これはそれほど重要ではありませんが、繰り返しますが、関数が50ミリ秒を超えるときではなく、関数を複数回呼び出すときに問題が発生します。私はあなたがあなたの答えを間違えていると思います。

  1. 1行1列の呼び出しをオフにしてコードをリロードし、製品エラーがないかどうかを確認してください。
  2. 2番目のスクリプトでエラーが発生した場合は、違反の期間に基づいてsetTimeOutを使用してください。
0
Cherif

1コンソールへ

2(「保存ログ」チェックボックス)付近のフィルターアイコンをクリックします。

3ティック "違反を隠す" チェックボックス


_編集_

この機能はChrome 58から削除されました。

違反を確認するには、ログ記録レベルのドロップダウンを[詳細]に変更します。

0
Sajan