【入門編】 ロングタスク(Long Tasks)とレンダリングの競合 – Webブラウザの仕組み実践ガイド

こんにちは!フロントエンドの現場を渡り歩いているチーフアーキテクトの私です。

Webサイトを作っていて、「なんだかスマホでスクロールするとカクカクするな……」「ボタンを押してから画面が変わるまでに、ほんの一瞬だけ引っかかりを感じるな……」とモヤモヤした経験はありませんか?

「自分のコードの書き方が悪いのかな」って、ちょっと落ち込んだりしていませんか?
大丈夫ですよ、安心してください。そのカクつきや引っかかりの正体は、あなたが未熟なせいではなく、Webブラウザの「お仕事の仕組み(ルール)」を知らなかっただけなんです。

今日は、ブラウザが裏側でどうやって私たちの書いたHTMLやJavaScriptを料理しているのか、そしてその過程で厄介な「渋滞」を起こしてしまうロングタスク(Long Tasks)について、身近な例えを交えながら、とことん優しく解き明かしていきましょう!

—

1. ブラウザは「超優秀だけど、同時に一つのことしかできない職人さん」

まず、Webブラウザの頭の中を覗いてみましょう。
ブラウザは、画面を描画したり、ユーザーのクリックを処理したり、JavaScriptを実行したりと、何でもこなすスーパーマンのように見えますよね。

でも実は、ブラウザの心臓部である「メインスレッド(中心となる作業台)」は、職人気質の一人親方なんです。この親方は、同時に複数の作業ができません。 一度に一つの作業を、順番に片付けていくしかできないのです。

身近な例えで考えてみましょう。
あなたは今、街の人気カフェのカウンターにいます。店員さんは1人だけです。

  • お客さんの注文を聞く(ユーザーからのクリックや入力)
  • カフェラテを作る(JavaScriptの計算やデータ処理)
  • カウンターをピカピカに拭いて、次の人を迎える準備をする(画面のレンダリング・描画)

この店員さん、ものすごく手際が良いのですが、1人しかいないので、もし「めちゃくちゃ手間のかかる特別な一杯(重たい処理)」の注文が入ると、どうなるでしょうか?
その作業に付きっきりになってしまい、他のお客さんの注文を聞けなくなったり、テーブルを拭く手が止まってしまったりしますよね。

これが、Webブラウザのメインスレッドで起きていることの正体です。

—

2. 犯人は「50msの壁」!ロングタスクが画面を凍らせる仕組み

ここで、今日の主役である「ロングタスク(Long Tasks)」が登場します。

Webの世界では、「50ms(ミリ秒=0.05秒)を超える長さの作業」をロングタスクと呼びます。
人間の目は非常にシビアで、画面の更新が1秒間に60回(つまり1コマあたり約16.6ms)行われないと、「カクついている」「滑らかじゃない」と感じてしまいます。

もし、ブラウザの親方が一つの作業(JavaScriptのループ処理や重たい計算など)に没頭し、50ms以上ずっと作業台を占有してしまったらどうなるでしょうか?

1. ユーザーが画面をスクロールしようとする(あるいはボタンを押す)。
2. しかし、親方は「今、大事な作業中だからちょっと待って!」と、その入力を無視せざるを得ない。
3. 画面の描画(アニメーションやスクロールの反映)もストップし、画面がフリーズしたようになる。

これが、ロングタスクがレンダリング(画面を描画するお仕事)を遅延させ、ユーザーにストレスを与えるメカニズムです。

カフェの例えに戻りましょう。
店員さんが、ものすごく時間のかかる「特製サイフォンコーヒー」の抽出を始めたとします。それが終わるまでの5分間、店員さんは他の作業が一切できません。その間、新しく並んだお客さんはずっと待たされることになります。これがロングタスクです。

—

3. どうすればいいの?「タスクを細かく分割する」という魔法

「じゃあ、重たい処理を書くときはどうすればいいの? 全部諦めなきゃいけないの?」
いいえ、そんなことはありません!ここで私たちフロントエンドエンジニアの出番です。

解決策はとってもシンプル。
「一気にやらずに、こまめに休憩を挟む(タスクを分割する)」ことです。

先ほどのカフェの店員さんなら、「サイフォンをセットしたら、一度お湯を沸かしている間に、並んでいるお客さんの注文を1人分だけ聞いておく。またコーヒーに戻る」という風に、細かく仕事を切り替えるイメージです。

これをプログラムの世界では、どのように表現するのでしょうか?
実際のコードを見てみましょう。

改善前:一気にやろうとしてブラウザを窒息させるコード

以下のコードは、数百万回もの重たい計算を、一気にブワッと実行してしまう例です。ブラウザはこれを受け取ると、計算が終わるまで画面の描画を一切放棄してしまいます。

// 【悪い例】一気に重たい処理を実行してしまう(ロングタスクの原因に!)
function runHeavyTask() {
console.log(“重たい処理を開始します…”);

// 途方もない回数のループ(これが50ms以上かかり、ブラウザをフリーズさせる)
for (let i = 0; i < 1000000000; i++) { // ひたすら計算するだけの重労働 } console.log("処理が完了しました!"); } // ボタンを押すと、画面が一時的にカクッと固まる document.getElementById("myButton").addEventListener("click", runHeavyTask);

改善後:タスクを分割して、ブラウザに「息継ぎ」をさせるコード

では、これをどう直せばいいのでしょうか?
現代のJavaScriptには、ブラウザの親方に「ねえ、ちょっと一息ついて、溜まっている画面描画や他の仕事をしていいよ!」とバトンタッチするための仕組み(`setTimeout` や `requestAnimationFrame`、あるいは `async/await`)が用意されています。

いくつかのパーツ(チャンク)に仕事を分けて、順番に実行するコードを見てみましょう。

/

  • 【良い例】重たい処理を小さな小分け(チャンク)にして実行する

/

// 重たい配列を、少しずつ分割して処理する関数
async function runHeavyTaskSafely() {
console.log(“分割した処理を開始します…”);

const totalSteps = 10; // 全体の作業を10個に分割するよ
let currentStep = 0;

function doChunk() {
return new Promise((resolve) => {
// 1回分の小さな仕事(これなら50ms以内に終わる!)
// ※ここでは擬似的に重たい処理をシミュレーションしています
const start = performance.now();
while (performance.now() – start < 10) { // 10msだけ計算する } currentStep++; resolve(); }); } // ループを回しつつ、1回終わるごとにブラウザに主導権を「お返し」する while (currentStep < totalSteps) { await doChunk(); // ここで「ちょっと待ってね、描画や他の仕事をしていいよ」とブラウザに譲る console.log(`進捗: ${currentStep} / ${totalSteps} 完了`); } console.log("すべての処理がスムーズに完了しました!"); } // これならボタンを押しても画面がカクつかず、なめらかに動きます document.getElementById("myButton").addEventListener("click", runHeavyTaskSafely); このコードのポイントは、`await doChunk();` の部分です。 一気にすべての仕事を終わらせるのではなく、「10msだけ計算したら、一度ブラウザに『お疲れ様!画面の描画やユーザーのスクロール処理をしていいよ!』とバトンを渡す」というキャッチボールを挟んでいます。 これによって、ブラウザの親方は定期的に息継ぎができるため、ユーザーが画面をスクロールしたり、他のボタンを押したりしたときにも、即座に反応できるようになるのです。 ---

まとめ:ブラウザに優しいコードが、ユーザーに優しいWebを作る

今回は、ロングタスクがレンダリングを遅延させる仕組みと、タスク分割による改善の魔法についてお話ししました。

  • ブラウザのメインスレッドは一人親方。同時に一つの仕事しかできない。
  • 50msを超える「ロングタスク」は、親方を拘束して画面をカクつかせる原因になる。
  • 重たい処理は小さく分割(チャンク化)し、ブラウザに「息継ぎのタイミング(お仕事のバトンタッチ)」をプレゼントしてあげよう。

Web制作やプログラミングを学び始めたばかりの頃は、「動けばいいや」と書きがちですが、こうしたブラウザの「中の人の気持ち」を少しだけ想像してあげると、書くコードの質が劇的に変わってきます。そして何より、あなたの作ったWebサイトを使うユーザーが、ストレスなく快適に笑顔で過ごせるようになりますよ。

焦らず、一歩ずつ、ご自身のペースで進んでいきましょう。
あなたのフロントエンドライフを、これからも応援しています!

コメント

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