【実務・中級編】 Long Tasks APIによるメインスレッド監視 – Webブラウザの仕組み実践ガイド

なぜ、あなたのWebサイトは「重い」のか?―― Long Tasks APIでメインスレッドの支配を解き放つ

現場でコードを書いていると、たまに「なぜか急にUIの反応が鈍くなる」という壁に突き当たることがあるだろう。クリックしても反応がない、スクロールがカクつく。調査ツールを立ち上げ、プロファイラを眺めては首を傾げる。

実はその「重さ」の正体は、ブラウザのメインスレッドを占拠している「Long Tasks(ロングタスク)」である可能性が高い。今日は、この泥沼に足を踏み入れないための、そして最悪の事態を検知するための「Long Tasks API」について、現場の知見を交えて深掘りしていく。

ブラウザの「心臓部」を理解する

まず、ブラウザのレンダリングエンジンがどう動いているか、改めて整理しよう。

ブラウザのメインスレッドは、「JavaScriptの実行」「スタイル計算」「レイアウト(リフロー)」「ペイント」「コンポジット(合成)」という、いわば一人二役どころか十役をこなす過酷な労働環境にある。

ここで重要なのは、これらが「シングルスレッド」で直列に処理されているという事実だ。メインスレッドで重いJavaScriptが実行されている間、ユーザーのクリックやスクロール、あるいはCSSアニメーションのための描画処理は「お預け」を食らう。

W3Cの仕様において、50msを超えるタスクは「Long Task」と定義されている。人間がUIの遅延を「ヌルヌル動いていない」と感じ始めるのがだいたい100ms前後であることを考えれば、50msという境界線は、ユーザー体験を維持するための「死守すべき防衛ライン」なのだ。

Long Tasks API:メインスレッドの監視員を雇う

この「何がメインスレッドを殺しているのか」を特定するために使うのが、`PerformanceObserver` を活用した `longtask` 型の監視だ。

以下に、実務でそのまま導入できる監視モジュールのサンプルを用意した。これをアプリケーションの初期化段階(`main.js`など)で実行しておけば、裏でこっそり発生している「犯人」を特定できる。

/

  • メインスレッドのLong Taskを監視し、
  • しきい値を超えたタスクをコンソールに警告する監視スクリプト

/
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// entry.durationはタスクの実行時間(ms)
// entry.startTimeはタスクが開始されたタイミング(ms)
console.warn(`[Long Task Detected] 実行時間: ${entry.duration.toFixed(2)}ms`);

// どのファイルが原因か特定するためのヒント
// ただし、これだけでは完全なスタックトレースは取れないため、
// 必要であればPerformance APIのより詳細な解析と組み合わせる
console.table({
name: entry.name,
duration: entry.duration,
startTime: entry.startTime,
attribution: entry.attribution // どの要素(iframeなど)が原因かを示す情報
});
}
});

// ‘longtask’型を監視するように設定
// これで50ms以上のタスクがメインスレッドで発生した瞬間にコールバックが発火する
observer.observe({ entryTypes: [‘longtask’] });

console.log(“メインスレッド監視を開始しました。”);

現場でこの情報をどう活かすか?

このコードを仕込むと、開発中やリリース後のSentryなどの監視ツールに、「とんでもない数値」が飛んでくるはずだ。そこで慌ててはいけない。次のステップで対処する。

1. 「犯人」の切り分け: `entry.attribution` を見る。もしiframeやサードパーティスクリプト(広告タグや解析ツール)が原因なら、それらのロード順や非同期化を検討する。
2. 分割統治: メインスレッドを占拠している大きなループ処理があれば、`requestIdleCallback` や `setTimeout` で細切れに実行するようにリファクタリングする。
3. Web Workerへの移行: 計算リソースを食う処理(データ整形や重いフィルタリング)は、メインスレッドから切り離してWeb Workerへ投げるのが、現代のフロントエンドにおける「最適解」だ。

最後に:完璧を求めすぎないこと

「50ms」という数字はあくまで目安だ。実際には、低スペックなデバイスでは50msでも致命的なカクつきになるし、強力なデスクトップPCなら100msでもユーザーは気づかないかもしれない。

重要なのは、「ブラウザが今、何に忙殺されているのか」を可視化する習慣を持つことだ。ツールに頼るだけでなく、自分の書いたコードが「今、メインスレッドを独占していないか?」と自問自答する癖をつける。それが、平凡なエンジニアと、真に洗練されたエンジニアを分かつ境界線になる。

さあ、まずはこの監視コードを仕込んで、あなたのアプリケーションの「裏の顔」を覗いてみるところから始めてみよう。意外なほど「無駄な計算」が見つかるはずだ。

コメント

タイトルとURLをコピーしました