最新のウェブブラウザの詳細(パート 4)

Mariko Kosaka

入力はコンポジタに送られます

今回は、Chrome の詳細について 4 部構成のブログシリーズの最後です。データがどのように処理されるかを ウェブサイトを表示するためのコードです前回の投稿では、レンダリング プロセスとコンポジタについて学びました。この投稿では ユーザー入力を受け取ったときにコンポジタがスムーズなインタラクションをどのように実現しているかを見てみましょう。

ブラウザの視点からの入力イベント

「入力イベント」が聞こえた場合テキストボックスでの入力やマウスクリックだけと思えるかもしれませんが、 ブラウザの観点から見ると、入力とはユーザーのあらゆる操作を指します。マウスホイールのスクロールは入力 タップやマウスオーバーも入力イベントです。

画面をタップするなどのユーザー操作が発生すると、ブラウザ プロセスが 見てみましょう。ただし、ブラウザ プロセスは、その操作が行われた場所のみを認識します。 タブ内のコンテンツはレンダラプロセスによって処理されますブラウザプロセスがイベントを送信し タイプ(touchstart など)とその座標をレンダラ プロセスに渡します。レンダラプロセスは イベントを適切に実行するには、イベント ターゲットを見つけ、アタッチされたイベント リスナーを実行します。

<ph type="x-smartling-placeholder">
</ph> 入力イベント <ph type="x-smartling-placeholder">
</ph> 図 1: ブラウザ プロセスを介してレンダラ プロセスにルーティングされる入力イベント
をご覧ください。

コンポジタが入力イベントを受け取る

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> 図 2: ページのレイヤの上にホバーしているビューポート

前回の投稿では、コンポジタがスクロールをスムーズに処理するために、 レイヤに分割されます。ページに入力イベント リスナーがアタッチされていない場合、Compositor スレッドは メインスレッドから完全に独立して新しい複合フレームを作成します。イベントで ページにアタッチされたでしょうかコンポジタ スレッドは、イベントに どうすればよいでしょうか。

高速でないスクロール可能な領域について

JavaScript の実行はメインスレッドの仕事であるため、ページが合成されるとコンポジタ スレッドが イベント ハンドラが接続されているページの領域を「非高速スクロール可能領域」としてマークします。方法 この情報があれば、コンポジタ スレッドは入力イベントをメインスレッドに その地域でイベントが発生したときに 通知を受け取ることができます入力イベントがこの領域の外側にある場合、 コンポジタ スレッドは、メインスレッドを待たずに新しいフレームの合成を続行します。

<ph type="x-smartling-placeholder">
</ph> 制限された非高速スクロール可能領域 <ph type="x-smartling-placeholder">
</ph> 図 3: 非高速スクロール可能領域への入力の図
をご覧ください。

イベント ハンドラを作成するときの注意

ウェブ開発での一般的なイベント処理パターンは、イベントの委任です。イベントをバブルで表示するので、 最上位の要素にイベント ハンドラを 1 つアタッチし、イベント ターゲットに基づいてタスクを委任できます。マイページ 次のようなコードを見たり記述したりしたことがあるかもしれません。

document.body.addEventListener('touchstart', event => {
    if (event.target === area) {
        event.preventDefault();
    }
});

すべての要素に対して 1 つのイベント ハンドラを記述するだけでよいため、このイベントのエルゴノミクスを考慮する必要があります。 委任パターンが魅力的です。しかし、ブラウザからコードを見てみると、 ページ全体が高速スクロールできない領域としてマークされます。つまり ページの特定の部分からの入力がアプリケーションで考慮されない場合、コンポジタ スレッドは メインスレッドと通信して、入力イベントが発生するたびに待機します。したがって、 コンポジタのスムーズ スクロール機能が無効になります。

<ph type="x-smartling-placeholder">
</ph> 全画面表示の非高速スクロール可能領域 <ph type="x-smartling-placeholder">
</ph> 図 4: ページ全体をカバーする非高速スクロール可能領域への入力の説明図
をご覧ください。

これを回避するには、イベントで passive: true オプションを渡して、 呼び出すことができます。これにより、メインスレッドでイベントをリッスンすることをブラウザに通知しますが、 コンポジタは先に進んで新しいフレームを合成することもできます。

document.body.addEventListener('touchstart', event => {
    if (event.target === area) {
        event.preventDefault()
    }
 }, {passive: true});

イベントがキャンセル可能かどうかを確認する

<ph type="x-smartling-placeholder">
</ph> ページ スクロール <ph type="x-smartling-placeholder">
</ph> 図 5: ページの一部を水平スクロールに固定したウェブページ
をご覧ください。

ページ内に、スクロール方向を水平スクロールのみに制限するボックスがあるとします。

ポインタ イベントで passive: true オプションを使用すると、ページ スクロールはスムーズですが、 制限するために、preventDefault に設定したい時刻までに縦方向のスクロールが開始された可能性があります スクロール方向を指定します。これを確認するには、event.cancelable メソッドを使用します。

document.body.addEventListener('pointermove', event => {
    if (event.cancelable) {
        event.preventDefault(); // block the native scroll
        /*
        *  do what you want the application to do here
        */
    }
}, {passive: true});

または、touch-action などの CSS ルールを使用して、イベント ハンドラを完全に削除することもできます。

#area {
  touch-action: pan-x;
}

イベント ターゲットを見つける

<ph type="x-smartling-placeholder">
</ph> ヒットテスト <ph type="x-smartling-placeholder">
</ph> 図 6: ペイント レコードを見て x.y 点に何が描画されるかを尋ねるメインスレッド
をご覧ください。

コンポジタ スレッドがメインスレッドに入力イベントを送信すると、最初にヒットが発生します。 イベント ターゲットを見つけます。ヒットテストでは、レンダリングで生成されたペイント レコードデータが使用されます。 イベントが発生した地点の座標の下に何があるかを調べます。

メインスレッドへのイベント ディスパッチを最小限に抑える

前回の投稿では、一般的なディスプレイが 1 秒間に 60 回画面を更新し、 スムーズなアニメーションのために、リズムに遅れないようにする必要があるのです。入力には、一般的なタッチ スクリーン デバイスは 1 秒間に 60 ~ 120 回タッチイベントを配信し、一般的なマウスは 1 秒間に 100 回イベントを配信します。 なります。入力イベントの忠実度が、画面を更新できないレベルを超えています。

touchmove のような連続イベントが 1 秒間に 120 回メインスレッドに送信された場合、 処理の遅れに比べて、ヒットテストと JavaScript の実行が過剰に 画面を更新できます。

<ph type="x-smartling-placeholder">
</ph> フィルタ未適用のイベント <ph type="x-smartling-placeholder">
</ph> 図 7: イベントがフレーム タイムラインにフラッドを引き起こし、ページジャンクが発生する
をご覧ください。

メインスレッドの過剰な呼び出しを最小限に抑えるために、Chrome では、 wheelmousewheelmousemovepointermovetouchmove など)が表示され、ディスパッチが次の時点まで遅れます。 次のrequestAnimationFrameの直前に表示されます

<ph type="x-smartling-placeholder">
</ph> 合併イベント <ph type="x-smartling-placeholder">
</ph> 図 8: 前と同じタイムラインだが、イベントが融合して遅延している
をご覧ください。

keydownkeyupmouseupmousedowntouchstarttouchend などの個別のイベント すぐにディスパッチされます。

getCoalescedEvents を使用してフレーム内イベントを取得する

ほとんどのウェブ アプリケーションでは、優れたユーザー エクスペリエンスを提供するには、統合されたイベントで十分です。 ただし、描画アプリケーションや、アプリケーション ベースのパスを touchmove 座標の場合、滑らかな線を引くために中間の座標が失われる可能性があります。その場合、 ポインタ イベントで getCoalescedEvents メソッドを使用して、これらの情報を取得できます。 イベントです。

<ph type="x-smartling-placeholder">
</ph> getCoalescedEvents <ph type="x-smartling-placeholder">
</ph> 図 9: スムーズなタッチ ジェスチャー パス(左側)、結合された限定的なパス(右側)
をご覧ください。
window.addEventListener('pointermove', event => {
    const events = event.getCoalescedEvents();
    for (let event of events) {
        const x = event.pageX;
        const y = event.pageY;
        // draw a line using x and y coordinates.
    }
});

次のステップ

このシリーズでは、ウェブブラウザの内部の仕組みについて説明しました。なぜなのか考えたことがなかったら DevTools では、イベント ハンドラに {passive: true} を追加するか、async と記述することをおすすめします。 属性を指定することをおすすめします。このシリーズで、ブラウザがこれらの属性を必要とする理由について より高速でスムーズなウェブ エクスペリエンスを実現します。

Lighthouse を使用する

ブラウザにとって適切なコードを作成したいけれども、どこから手を付けたらよいかわからない場合は、 Lighthouse は、ウェブサイトの監査を実行し、 適切に実施されたことと改善すべき点について報告します。監査のリストを確認する ブラウザがどのようなことを関心を持っているかを把握できます。

パフォーマンスの測定方法の詳細

パフォーマンスの微調整はサイトによって異なる場合があるため、パフォーマンスを測定することが重要です サイトに最適なものを判断しますChrome DevTools チームには サイトのパフォーマンスを測定する方法をご覧ください。

サイトに機能ポリシーを追加する

さらに一歩踏み込んで考える場合、機能ポリシーは ウェブ プラットフォーム機能について説明します。オンにしています 機能ポリシーは、アプリの特定の動作を保証し、ミスを防ぐものです。 たとえば、アプリが解析をブロックしないようにするには、 同期スクリプト ポリシーが適用されます。sync-script: 'none' を有効にすると、パーサーをブロックする JavaScript が次のように動作します。 実行されないようにできます。これにより、コードによってパーサーが パーサーの一時停止を心配する必要はありません。

まとめ

ありがとう

ウェブサイトの構築を始めた当初は、コードの記述方法と 生産性が上がりますこれらは重要ですが 記述したコードをブラウザが受け取ります。最新のブラウザでは、 ウェブエクスペリエンスが向上しますコードを整理して ブラウザの利便性を高めることで ひいてはユーザーエクスペリエンスが向上しますブラウザの使い方をするためのクエストにぜひご協力ください。

初期の下書きにご協力いただいた皆様に心よりお礼を申し上げます。 共有先): Alex RussellPaul Irish 氏、 Meggin Kearney Eric Bidelman 氏 Mathias BynensAddy Osmani安田木久子氏 Nasko Oskov Charlie Reis です

このシリーズはいかがでしたか?今後の投稿についてご不明な点やご意見がございましたら、 以下のコメント欄または @kosamari からご意見をお寄せください。 。