ウェブ パフォーマンスを簡単に - Google I/O 2018 エディション

Google IO 2018 では、ウェブ パフォーマンスを簡単に改善できるツール、ライブラリ、最適化手法についてまとめました。ここでは、Oodles Theater アプリを使用してその方法について説明します。また、予測読み込みの試験運用や Guess.js の新しい取り組みについてもお話しします。

Addy Osmani
Addy Osmani
Ewa Gasperowicz

この 1 年間、私たちはウェブを高速化し、パフォーマンスを向上させる方法を模索してきました。そこから生まれた新しいツール、アプローチ、ライブラリは、この記事で皆様にご紹介したいと思います。パート 1 では、Oodles Theater アプリの開発時に実際に使用した最適化手法を紹介します。パート 2 では、予測読み込みのテストと新しい Guess.js イニシアチブについてお話しします。

パフォーマンスのニーズ

インターネットの容量は年々増しています。ウェブの状態を確認すると、モバイルのウェイト ページの中央値が約 1.5 MB で、その大部分が JavaScript と画像であることがわかります。

ウェブサイトのサイズが大きくなることも、ネットワーク レイテンシ、CPU の制限、レンダリング ブロック パターン、余分なサードパーティ コードなどの要因も加わり、複雑なパフォーマンスの問題の一因となっています。

ほとんどのユーザーは、自分のニーズの UX 階層の最上位にスピードがあると評価しています。ページの読み込みが完了するまで多くの処理を実行できないため、これも不思議ではありません。ページから価値を引き出すことはできません。ページの美しさを賞賛することもできません。

UX 階層のピラミッド
図 1.ユーザーにとって速度はどの程度重要ですか?(Speed Matters、Vol. 3)

パフォーマンスはユーザーにとって重要ですが、どこから最適化を開始すべきかわからないことにも感じます。幸い、便利なツールがあります。

Lighthouse - パフォーマンス ワークフローのベース

Lighthouse は Chrome DevTools のひとつで、ウェブサイトを監査して改善方法のヒントを提供するツールです。

Google は最近、日々の開発ワークフローで非常に役立つ新しいパフォーマンス監査をいくつかリリースしました。

新しい Lighthouse の監査
図 2.Lighthouse の新しい監査

具体的な例として、Oodles Theater アプリで、その活用方法を見てみましょう。これは、小さなデモ ウェブアプリで、おすすめのインタラクティブな Google Doodle を試したり、ゲームを 1 つか 2 つプレイしたりできるものです。

アプリを作成する際に、できる限りパフォーマンスを高めるようにしたいと考えました。最適化の出発点は、Lighthouse レポートでした。

Oodles アプリの Lighthouse レポート
図 3.Oodles アプリの Lighthouse レポート

Lighthouse レポートで確認できるアプリの初期パフォーマンスは、かなりひどいものでした。 3G ネットワークでは、最初の意味のある描画が行われるか、アプリが操作可能になるまで 15 秒待つ必要がありました。Lighthouse ではサイトの多くの問題がハイライト表示され、全体的なパフォーマンス スコアは 23 でした。

ページの重さは約 3.4 MB で、どうしても脂肪を減らす必要がありました。

これが、最初のパフォーマンス上の課題として始まりました。それは、全体的なエクスペリエンスに影響を与えずに簡単に削除できる要素を見つけることです。

パフォーマンスの最適化の機会

不要なリソースを削除する

空白やコメントは安全に削除できるものです。

圧縮によるメリット
図 4.JavaScript と CSS を最小化して圧縮する

Lighthouse では、この最適化案が非圧縮 CSS と JavaScript の監査でハイライト表示されます。ビルドプロセスには Webpack を使用していたため、圧縮するために Uglify JS プラグインを使用しました。

圧縮は一般的なタスクであるため、使用するビルドプロセスに応じて、すぐに使えるソリューションが見つかるはずです。

このスペースには、[テキスト圧縮を有効にする] も便利な監査です。非圧縮ファイルを送信する理由はありません。最近では、ほとんどの CDN でこの機能がデフォルトでサポートされています。

当社はコードをホストするために Firebase Hosting を使用していましたが、Firebase はデフォルトで gzipping を有効にしています。妥当な CDN でコードをホストしたおかげで、これを無料で手に入れました。

gzip は非常によく使用される圧縮方法ですが、ZopfliBrotli などの他のメカニズムも注目を集めています。Brotli はほとんどのブラウザでサポートしており、バイナリを使用してアセットをサーバーに送信する前に事前に圧縮できます。

効率的なキャッシュ ポリシーを使用する

次のステップは、不要な場合にリソースを 2 回送信しないようにすることでした。

Lighthouse での非効率的なキャッシュ ポリシーの監査により、キャッシュ戦略を最適化してこれを実現できることがわかりました。Google のサーバーに max-age の有効期限ヘッダーを設定することで、ユーザーが繰り返しアクセスした際に、以前ダウンロードしたリソースを再利用できるようにしました。

理想的には、可能な限り長い期間安全にできるだけ多くのリソースをキャッシュに保存することと、更新されたリソースを効率的に再検証するための検証トークンを提供することが理想的です。

使用していないコードを削除する

ここまでで、不要なダウンロードの明白な部分を削除しましたが、わかりにくい部分についてはどうでしょうか。(未使用のコードなど)。

DevTools のコード カバレッジ
図 5.コード カバレッジを確認する

場合によっては、実際には不要なコードがアプリに含まれていることがあります。これは特に、アプリの作業時間が長い場合に生じます。チームや依存関係が変わったり、孤立したライブラリが取り残されたりすることがあります。実際に起こったことです

当初は、マテリアル コンポーネント ライブラリを使用してアプリのプロトタイプを迅速に作成していましたが、その後、よりカスタマイズされた外観に移行しましたが、そのライブラリは完全に忘れていました。幸い、コード カバレッジ チェックは、バンドル内で再検出するのに役立ちました。

DevTools で、アプリのランタイムと読み込み時間の両方について、コード カバレッジの統計情報を確認できます。下のスクリーンショットを見ると、2 つの大きな赤いストライプが確認できます。CSS の 95% 以上が使用されておらず、JavaScript もかなりの量です。

この問題は、未使用の CSS ルールの監査でも検出されました。400KB 以上も節約できましたコードに戻り、ライブラリの JavaScript 部分と CSS 部分の両方を削除しました。

MVC アダプターを削除すると、スタイルが 10 KB になります
図 6.MVC アダプターを削除すると、スタイルが 10 KB になります。

これにより、CSS バンドルが 20 倍になり、2 行の小さな commit にはかなり適しています。

もちろん、パフォーマンス スコアも向上し、操作可能になるまでの時間も大幅に向上しました。

しかし、このような変更を行った場合、指標とスコアのみを確認するだけでは十分ではありません。実際のコードの削除にはリスクがないので、潜在的なリグレッションに常に注意する必要があります。

私たちのコードは 95% 使用されていませんでした。この 5% がまだどこかに存在します。コンポーネントの 1 つがまだライブラリのスタイル(Doodle スライダーの小さな矢印)を使っていたようです。ただし、サイズが小さいため、これらのスタイルを手動でボタンに組み込むことができました。

ライブラリがないためボタンが機能しない
図 7.1 つのコンポーネントがまだ削除されたライブラリを使用していた

そのため、コードを削除する場合は、視覚的な回帰を防ぐために、適切なテスト ワークフローを用意してください。

膨大なネットワーク ペイロードを回避する

リソースが大きい場合、ウェブページの読み込みが遅くなることは周知の事実です。ユーザーに料金がかかる場合があり、データプランに大きな影響を与える可能性があるため、この点に注意することが非常に重要です。

Lighthouse は、Enormous ネットワーク ペイロードの監査を使用して、一部のネットワーク ペイロードの問題を検出しました。

膨大なネットワーク・ペイロードを検知
図 8.膨大なネットワーク ペイロードを検出する

ここでは、3 MB を超えるコードが出荷されていることがわかりました。特にモバイルでは、これはかなりの量です。

Lighthouse では、このリストの一番上に、非圧縮コードが 2 MB ある JavaScript ベンダー バンドルがあることが強調されています。これは webpack でも指摘されている問題です。

格言にあるように、最速のリクエストとは実行されないリクエストです。

理想的には、ユーザーに配信するすべてのアセットの価値を測定し、それらのアセットのパフォーマンスを測定して、初期段階で実際に配布する価値があるかどうかを判断する必要があります。これらのアセットは、アイドル時間中に遅延、遅延読み込み、または処理される場合があるためです。

今回は、多くの JavaScript バンドルを扱っているため、JavaScript コミュニティには JavaScript バンドル監査ツールが多数用意されているため、とても助かりました。

JavaScript バンドルの監査
図 9.JavaScript バンドル監査

まず Webpack バンドル アナライザを使用していたところ、解析済みの JavaScript が 1.6 MB ある Unicode という依存関係が大量に含まれていることがわかりました。

次に、エディタでビジュアル コード用のインポート費用プラグインを使用して、インポートするすべてのモジュールの費用を可視化することができました。これにより、このモジュールを参照していたコードが含まれているコンポーネントを見つけることができました。

その後、別のツールである BundlePhobia に切り替えました。このツールを使うと、任意の NPM パッケージの名前を入力すると、そのパッケージの圧縮や gzip での推定サイズを実際に確認できます。以前使用していたスラッグ モジュールの重量がわずか 2.2 KB の優れた代替モジュールが見つかったため、モジュールを切り替えました。

これは当社のパフォーマンスに大きな影響を与えました。この変更を行い、JavaScript バンドルサイズを削減する他の機会を見つけることで、2.1 MB のコードを節約できました。

これらのバンドルの gzip 圧縮と圧縮サイズを考慮すると、全体で 65% の改善が見られました。このプロセスを実施する価値があることがわかりました。

そのため、通常はサイトやアプリで不要なダウンロードが発生しないようにしてください。 アセットのインベントリを作成し、パフォーマンスへの影響を測定すると、大きな違いが生じる可能性があるため、アセットを公正に定期的に監査してください。

コード分割で JavaScript の起動時間を短縮

大規模なネットワーク ペイロードはアプリに大きな影響を与える可能性がありますが、JavaScript についても非常に大きな影響があります。

JavaScript は最も高価なアセットです。モバイルでは、大量の JavaScript バンドルを送信すると、ユーザーがユーザー インターフェース コンポーネントを操作できるようになるまでに遅れが生じることがあります。つまり、意味のあることは何も起こらなくても、ユーザーは UI をタップできます。そのため、JavaScript のコストが高い理由を理解することは重要です。

ブラウザが JavaScript を処理する仕組みです。

JavaScript 処理
図 10.JavaScript 処理

まず、スクリプトをダウンロードする必要があります。JavaScript エンジンでは、そのコードを解析してコンパイルし、実行する必要があります。

これらのフェーズは、デスクトップ マシンやノートパソコンなどのハイエンド デバイス、さらにはハイエンド スマートフォンでそれほど時間はかかりません。しかし、標準的なスマートフォンでは、このプロセスにかかる時間は 5 ~ 10 倍になることがあります。インタラクティビティを 遅らせてしまう原因はあります

アプリのこのような問題を発見しやすくするため、Lighthouse に JavaScript の起動時間の監査を新たに導入しました。

JavaScript の起動時間
図 11.JavaScript 起動時の監査

Oodle アプリの場合、JavaScript の起動にかかった時間は 1.8 秒でした。その結果、すべてのルートとコンポーネントを 1 つのモノリシック JavaScript バンドルに静的にインポートしていました。

これを回避する方法として、コード分割があります。

コード分割はピザのようなもの

コード分割とは、ピザ全体に相当する JavaScript をユーザーに提供するのではなく、ユーザーが必要なときに一度に 1 スライスずつだけ渡すようにするものです。

コード分割は、ルートレベルまたはコンポーネント レベルで適用できます。React と React Loadable、Vue.js、Angular、Polymer、Preact、その他の複数のライブラリで効果を発揮します。

アプリケーションにコード分割を組み込み、静的インポートから動的インポートに切り替え、必要に応じてコードを非同期で遅延読み込みできるようになりました。

動的インポートによるコード分割
図 13.動的インポートによるコード分割

これにより、バンドルのサイズが縮小されるだけでなく、JavaScript の起動時間が短縮されました。処理時間は 0.78 秒になり、アプリは 56% 高速化されました。

一般に、JavaScript を多用するエクスペリエンスを構築する場合は、必要とするユーザーにのみコードを送信するようにしてください。

コード分割などのコンセプトを利用し、ツリー シェイキングなどのアイデアを検討し、webpack を使用している場合にライブラリ サイズを削減する方法について webpack-libs-optimizations リポジトリを参照してください。

画像を最適化する

画像読み込みのパフォーマンスに関するジョーク

Oodle アプリでは多くの画像を使用しています。残念ながら Lighthouse からは 私たちと比べて あまり意欲的ではなかったようです実際、画像関連の 3 つの監査すべてで不合格となりました。

画像を最適化するのを忘れていたり、画像のサイズが正しく設定されていなかったり、他の画像形式を使用することである程度の成果をあげていました。

画像の監査
図 14.Lighthouse イメージの監査

まず、画像の最適化から始めました。

1 回限りの最適化では、ImageOptimXNConvert などのビジュアル ツールを使用できます。

より自動化されたアプローチは、imagemin などのライブラリを使用して画像最適化ステップをビルドプロセスに追加することです。

これにより、今後追加される画像が自動的に最適化されるようになります。 Akamai などの一部の CDN や、CloudinaryFastlyUploadcare などのサードパーティ ソリューションでは、包括的な画像最適化ソリューションが提供されます。これらのサービスで画像をホストするだけでもかまいません。

コストやレイテンシの問題でこれを行わない場合は、ThumborImageflow などのプロジェクトが自己ホスト型の代替手段を提供します。

最適化前と最適化後
図 15.最適化前と最適化後

Webpack では背景 PNG が大きすぎるとフラグが付けられました。ビューポートに合わせてサイズを正しく設定し、ImageOptim で実行した結果、許容範囲である 100 KB に縮小されました。

サイトの複数の画像について同じ操作を繰り返すことで、ページ全体のデータ量を大幅に減らすことができました。

アニメーション コンテンツに適した形式を使用する

GIF はかなり高額になる可能性があります。驚いたことに、GIF 形式はそもそもアニメーション プラットフォームとして想定したものではありません。したがって、より適切な動画形式に切り替えることで、ファイルサイズを大幅に節約できます。

Oodle アプリでは、ホームページのイントロ シーケンスとして GIF を使用していました。Lighthouse によると、 より効率的な動画形式に切り替えることで、7 MB 以上削減できる可能性があります。このクリップの重さは約 7.3 MB で、一般的なウェブサイトには大きすぎるため、2 つのソースファイル(mp4 と WebM)を含む動画要素に変換し、ブラウザのサポートを拡大しました。

アニメーション GIF を動画に置き換える
図 16.アニメーション GIF を動画に置き換える

FFmpeg ツールを使用して、アニメーション GIF を mp4 ファイルに変換しました。WebM 形式を使用すると、費用をさらに削減できます。ImageOptim API でこのような変換を行えます。

ffmpeg -i animation.gif -b:v 0 -crf 40 -vf scale=600:-1 video.mp4

この変換のおかげで、体重全体の 80% 以上を節約できました。約 1MB に減りました

それでも、特に帯域幅が制限されているユーザーにとっては、1 MB はケーブルを押し下げるための大きなリソースです。幸いなことに、Effective Type API を使用することで、帯域幅が低速であることに気づき、その代わりにはるかに小さい JPEG を提供できます。

このインターフェースは、実質的なラウンドトリップ時間とダウン時間の値を使用して、ユーザーが使用しているネットワークの種類を推定します。これは単に文字列、slow 2G、2G、3G、または 4G を返します。そのため、この値に応じて、ユーザーが 4G 未満に接続している場合は、動画要素を画像に置き換えることができます。

if (navigator.connection.effectiveType) { ... }

エクスペリエンスは多少軽減されますが、低速な接続でもサイトは使用できます。

オフスクリーン画像の遅延読み込みを行う

カルーセルやスライダー、非常に長いページでは、ユーザーがすぐにページを見なくても画像が読み込まれることがよくあります。

この動作は、Lighthouse のオフスクリーン画像監査で報告されます。DevTools のネットワーク パネルでは、ご自身で確認することもできます。ページに画像しか表示されていないにもかかわらず、大量の画像が届いた場合は、遅延読み込みを検討してみてください。

遅延読み込みはブラウザではまだネイティブでサポートされていないため、この機能を追加するには JavaScript を使用する必要があります。Lazysizes ライブラリを使用して、Oodle のカバーに遅延読み込み動作を追加しました。

<!-- Import library -->
import lazysizes from 'lazysizes'  <!-- or -->
<script src="lazysizes.min.js"></script>

<!-- Use it -->

<img data-src="image.jpg" class="lazyload"/>
<img class="lazyload"
    data-sizes="auto"
    data-src="image2.jpg"
    data-srcset="image1.jpg 300w,
    image2.jpg 600w,
    image3.jpg 900w"/>

Lazysizes は、要素の可視性の変化を追跡するだけでなく、最適なユーザー エクスペリエンスのためにビューの近くにある要素を積極的にプリフェッチするのでスマートです。また、オプションで IntersectionObserver の統合も利用できるため、非常に効率的な可視性のルックアップが行えます。

この変更後、画像はオンデマンドで取得されます。このトピックについてさらに詳しく知りたい場合は、images.guide をご覧ください。これは非常に便利で包括的なリソースです。

ブラウザが重要なリソースを早期に提供できるよう支援する

ブラウザに送信されるすべてのバイトの重要度が同じというわけではありません。ブラウザはこのことを認識します。多くのブラウザには、最初に何を取得するかを決定するヒューリスティック技術があります。そのため、画像やスクリプトの前に CSS を取得することもあります。

たとえば、ページの作成者として、本当に重要なことをブラウザに通知することで、有用な情報が得られます。幸いなことに、ここ数年、ブラウザ ベンダーは、link rel=preconnectpreloadprefetch などのリソースヒントなど、この問題の解決に役立つ多くの機能を追加してきました。

ウェブ プラットフォームに導入されたこれらの機能は、ブラウザが適切なタイミングで適切なものを取得するのに役立ちます。代わりにスクリプトを使用して行われるカスタム読み込みのロジックベースのアプローチよりも効率的です。

それらの機能を効果的に使用するために、Lighthouse がどのように役立つのかを見ていきましょう。

Lighthouse ではまず、どのオリジンに対してもコストのかかるラウンド トリップを複数回行わないよう配慮しています。

あらゆる出発地と複数回の、コストのかかる往復を避ける
図 17.あらゆる出発地と複数回の、コストのかかるラウンド トリップを避ける

Oodle アプリの場合、実際には Google Fonts を多用しています。Google Font スタイルシートをページに挿入すると、最大で 2 つのサブドメインが接続されます。Lighthouse からわかるのは、その接続をウォームアップできれば、初期接続時間を最大 300 ミリ秒短縮できるということです。

link rel preconnect を利用すると、その接続レイテンシを効果的にマスキングできます。

特に、フォント フェース CSS が googleapis.com でホストされ、フォント リソースが Gstatic でホストされている Google Fonts では、これは非常に大きな影響を及ぼす可能性があります。この最適化を適用することで、数百ミリ秒を削減できました。

Lighthouse は次に、キーリクエストをプリロードするよう提案します。

キー リクエストをプリロードする
図 18.キー リクエストのプリロード

<link rel=preload> は非常に強力で、現在のナビゲーションの一部としてリソースが必要であることをブラウザに通知し、可能な限り早くブラウザがリソースを取得しようとします。

今度は Lighthouse から、主要なウェブフォント リソースをプリロードするよう指示されました。これは、2 つのウェブフォントで読み込むためです。

ウェブフォントへのプリロードは次のようになります。rel=preload を指定して as を渡し、フォントのタイプを指定してから、読み込むフォントのタイプ(woff2 など)を指定します。

これがページに及ぼす影響はかなり大きいです。

リソースのプリロードの影響
図 19.リソースのプリロードの影響

通常、link rel プリロードを使用しないと、ウェブフォントがページにとって重要な場合、ブラウザはまず HTML を取得して CSS を解析し、その後のどこかで最終的にウェブフォントを取得します。

リンク URL プリロードを使用すると、ブラウザは HTML を解析するとすぐに、ウェブフォントの取得をかなり早い段階で開始できます。今回のアプリの場合、ウェブフォントを使用したテキストのレンダリングに要する時間を 1 秒短縮できました。

Google Fonts を使用してフォントをプリロードしようとすると、簡単ではありませんが、問題点が 1 つあります。

スタイルシートのフォント フェースに指定されている Google Font URL は、フォントチームが定期的に更新しているものがありました。これらの URL は期限切れになるか、定期的に更新されることがあるため、フォントの読み込み処理を完全に制御する必要がある場合は、ウェブフォントを自己ホストすることをおすすめします。リンクのプリロードなども 利用できるので便利です

今回の例では、ウェブフォントの一部をオフラインで設定してローカルに設定するには、Google Web Fonts Helper ツールが非常に便利であることがわかりました。ぜひこのツールをご活用ください。

ウェブフォントを重要なリソースの一部として使用している場合でも、JavaScript を使用している場合でも、ブラウザが重要なリソースをできるだけ早く提供できるようにしてください。

試験運用版: 優先度のヒント

今日は特別なお知らせがあります。リソースヒントやプリロードなどの機能に加え、Google では、優先ヒントと呼ぶ新しい試験運用版のブラウザ機能の開発に取り組んでいます。

最初に表示されるコンテンツの優先度を設定する
図 20.優先度のヒント

これは、リソースの重要性をブラウザに知らせることができる新機能です。低、高、自動の値を持つ新しい属性の重要度を公開します。

これにより、重要性の低いリソース(重要性の低いスタイル、画像、フェッチ API 呼び出しなど)の優先度を下げて、競合を減らすことができます。ヒーロー画像など重要度の高い項目の 優先度を上げることもできます

Oodle アプリの場合、実際に最適化できる実用的な場所が 1 つになりました。

最初に表示されるコンテンツの優先度を設定する
図 21.最初に表示されるコンテンツの優先度を設定する

画像に遅延読み込みを追加する前は、ブラウザでこの画像カルーセルをすべての落書きとともに作成し、ブラウザはカルーセルの開始時にすべての画像を早い段階で高い優先度で取得していました。残念ながら ユーザーにとって最も重要なのは カルーセルの中央の画像でした背景画像の重要度を非常に低く、前景の重要度を非常に高く設定し、低速の 3G で 2 秒の影響があったため、画像を取得してレンダリングするまでの時間を 2 秒にしました。とても良い体験です。

この機能を Canary で数週間以内に提供できるよう努めていますので、今後の情報にご注目ください。

ウェブフォントの読み込み方法を用意する

タイポグラフィは優れたデザインの基本です。ウェブフォントを使用している場合は、理想的にはテキストのレンダリングをブロックせず、目に見えないテキストも表示しないようにします。

現在は Lighthouse でハイライト表示され、ウェブフォントの読み込み中に目に見えないテキストを避けるという監査が表示されます。

ウェブフォントの読み込み中にテキストが目に見えないようにする
図 22.ウェブフォントの読み込み中に目に見えないテキストを避ける

フォント フェイス ブロックを使用してウェブフォントを読み込む場合、ウェブフォントの取得に時間がかかる場合の処理をブラウザが決定します。一部のブラウザは、システム フォントにフォールバックする前に最大 3 秒待機し、最終的にフォントがダウンロードされるとフォントをスワップアウトします。

この目に見えないテキストを避けようとしているので、ウェブフォントに時間がかかりすぎていたら、今週のおなじみの Doodle を見ることはできなかったでしょう。幸いなことに、font-display という新機能を使用することで、実際にはこのプロセスをより細かく制御できます。

    @font-face {
      font-family: 'Montserrat';
      font-style: normal;
      font-display: swap;
      font-weight: 400;
      src: local('Montserrat Regular'), local('Montserrat-Regular'),
          /* Chrome 26+, Opera 23+, Firefox 39+ */
          url('montserrat-v12-latin-regular.woff2') format('woff2'),
            /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
          url('montserrat-v12-latin-regular.woff') format('woff');
    }

フォント表示では、ウェブフォントのスワップにかかる時間に基づいて、ウェブフォントのレンダリング方法またはフォールバック方法を決定できます。

ここでは、フォントの表示を入れ替えています。Swap では、フォント フェースのブロック期間が 0 秒で、スワップ期間が無限になります。つまり、フォントの読み込みに時間がかかる場合、ブラウザは代替フォントを使用してすぐにテキストを描画します。フォントフェースが使用可能になると スワップされます

このアプリの場合、非常に早い段階で意味のあるテキストを表示し、準備ができたらウェブフォントに移行できる点が優れている点です。

フォント表示の結果
図 23.フォント表示の結果

一般に、ウェブフォントを使用している場合は、ウェブの大部分がそうであるように、優れたウェブフォントの読み込み方法を用意します。

フォントの読み込みを最適化するために使用できるウェブ プラットフォーム機能は多数ありますが、Zach Leatherman の Web Font Recipes リポジトリも参考にしてください。

レンダリング ブロック スクリプトを削減する

アプリケーションの他の部分は、ダウンロード チェーンの早い段階でプッシュすることで、少なくとも少し前に基本的なユーザー エクスペリエンスを提供できます。

Lighthouse のタイムライン ストリップを見ると、すべてのリソースの読み込みが完了する最初の数秒間、ユーザーがコンテンツをまったく表示できないことがわかります。

スタイルシートのレンダリングをブロックする機会を減らす
図 24.スタイルシートでレンダリングをブロックする機会を減らす

外部スタイルシートをダウンロードして処理すると、レンダリング プロセスが進まなくなります。

いくつかのスタイルを少し早めに配信することで、クリティカル レンダリング パスの最適化を試すことができます。

この最初のレンダリングに関与するスタイルを抽出し、HTML にインライン化すると、ブラウザは外部スタイルシートが到着するのを待たずにすぐにレンダリングできます。

今回は、Critical という NPM モジュールを使用して、ビルドステップで index.html の重要なコンテンツをインライン化しました。

手間のかかる作業のほとんどはこのモジュールで行っていましたが、異なるルート間でスムーズに機能させるには、まだ少し難しい作業でした。

注意していないか、サイトの構造が非常に複雑な場合、App Shell アーキテクチャを最初から計画していなかった場合、このタイプのパターンを導入することが非常に困難になる可能性があります。

そのため、早い段階でパフォーマンスを考慮することが重要です。最初からパフォーマンスを考慮して設計しないと、後で問題が発生する可能性が高くなります。

最終的にはリスクが報われ、なんとか動作させることができ、アプリがコンテンツをより早く配信し始め、最初の有意義な描画時間が大幅に短縮されました。

結果

サイトに適用したパフォーマンス最適化の長いリストでした。結果を見ていきましょう最適化前と最適化後の 3G ネットワーク上の中規模のモバイル デバイスへのアプリのロード方法を以下に示します。

Lighthouse のパフォーマンス スコアが 23 から 91 に上がり、スピードという点では かなり進歩していますこれらの変更はすべて、Lighthouse レポートを継続的にチェックして確認することで実現しました。Google がすべての改善を技術的に実装した方法については、Google のリポジトリ(特に、そこに収容された PR)をご覧ください。

予測パフォーマンス - データドリブンのユーザー エクスペリエンス

Google は、ML は多くの分野で未来にとって素晴らしい機会になると考えています。将来的にテストが促進されることを期待しているのは、実際のデータが私たちが作成するユーザー エクスペリエンスの指針になる可能性があるということです。

現在、Google はユーザーが何を求めているか、何が必要か、つまりプリフェッチ、プリロード、または事前キャッシュする価値のあるものについて、多くのランダムな決定を行っています。推測で正しいと言えば、少量のリソースを優先することはできても、ウェブサイト全体に拡張するのは実に困難です。

現在、最適化に活かすためのデータがすでにあります。 Google Analytics Reporting API を使って、次のトップページと、サイト内の任意の URL の離脱率を確認し、どのリソースを優先すべきかについて結論を導き出すことができます。

これを適切な確率モデルと組み合わせると、コンテンツを積極的に過剰にプリフェッチしてユーザーのデータを無駄にすることがなくなります。Google アナリティクスのデータを利用し、マルコフ連鎖ニューラル ネットワークなどの ML とモデルを使用して、このようなモデルを実装できます。

ウェブアプリ向けのデータドリブンなバンドル
図 25.ウェブアプリのデータドリブン バンドル

このテストを容易にするために、Google は Guess.js という新しいイニシアチブを発表します。

Guess.js
図 26.Guess.js

Guess.js は、ウェブ向けのデータドリブンなユーザー エクスペリエンスに重点を置いたプロジェクトです。Google は、このデータを使用してウェブ パフォーマンスを向上させ、さらに先へ進むためのデータを探求するきっかけになれば幸いです。すべてオープンソースで GitHub で入手できますこれは、Minko Gechev 氏、Gatsby の Kyle Matthews 氏、Katie Hempenius 氏、その他多数のオープンソース コミュニティと共同で構築されました。

Guess.js をチェックして、ぜひご感想をお聞かせください。

まとめ

スコアと指標はウェブの速度を向上させるのに役立ちますが、あくまで手段であり、目標そのものではありません。

外出先でページの読み込みが遅くなるという経験は誰にでもあるでしょう。しかし、このたび、読み込みが速く、より快適なエクスペリエンスをユーザーに提供できるようになりました。

パフォーマンスの向上は長い道のりです。小さな変化が大きな成果につながります。適切な最適化ツールを使用し、Lighthouse のレポートを定期的に確認することで、ユーザーにより優れたインクルーシブなエクスペリエンスを提供できます。

Ward Peeters、Minko Gechev、Kyle Mathews、Katie Hempenius、Dom Farolino、Yoav Weiss、Susie Lu、Utsunomiya、Tom Ankers、Lighthouse、Google Doodles に感謝します。