Google IO 2018 では、ウェブ パフォーマンスの改善を容易にするツール、ライブラリ、最適化手法のまとめを発表しました。ここでは、Oodles Theater アプリを使用して、これらの機能について説明します。また、予測読み込みと新しい Guess.js イニシアチブのテストについても説明します。
過去 1 年間、Google はウェブの高速化とパフォーマンスの向上に取り組んできました。これにより、新しいツール、アプローチ、ライブラリが生まれました。この記事では、それらについて説明します。前半では、Oodles Theater アプリの開発時に実際に使用した最適化手法について説明します。後半では、予測読み込みと新しい Guess.js イニシアチブに関するテストについて説明します。
パフォーマンスの必要性
インターネットは年々重くなっていきます。ウェブの状況を確認すると、モバイル ページの平均サイズは約 1.5 MB で、その大部分は JavaScript と画像です。
ウェブサイトのサイズの増大は、ネットワーク レイテンシ、CPU の制限、レンダリング ブロック パターン、不要なサードパーティ コードなどの他の要因とともに、複雑なパフォーマンス パズルにつながっています。
ほとんどのユーザーは、UX のニーズ階層において、速度を最優先事項と評価しています。これは、ページの読み込みが完了するまで、あまり多くのことを行えないため、驚くべきことではありません。ページから価値を引き出すことはできません。その美しさを楽しむこともできません。
![UX 階層ピラミッド](https://web.dev/static/articles/web-performance-made-easy/image/ux-hierarchy-piramide-9a38f1858336f.png?hl=ja)
パフォーマンスはユーザーにとって重要ですが、最適化を開始する場所を見つけるのは秘密のようでもあります。幸い、その過程をサポートするツールがいくつかあります。
Lighthouse - パフォーマンス ワークフローの基盤
Lighthouse は Chrome DevTools の一部で、ウェブサイトを監査し、改善方法のヒントを提供します。
Google は最近、日常的な開発ワークフローで非常に役立つ新しいパフォーマンス アудитをリリースしました。
![新しい Lighthouse 監査](https://web.dev/static/articles/web-performance-made-easy/image/new-lighthouse-audits-a5c01f6ee0cf4.png?hl=ja)
では、Oodles Theater アプリという実用的な例で、これらの機能の活用方法を見てみましょう。これは小さなデモ用ウェブアプリで、お気に入りのインタラクティブな Google Doodle を試したり、ゲームをプレイしたりできます。
アプリの開発にあたっては、できるだけ高いパフォーマンスを実現することを目標としました。最適化の開始点は Lighthouse レポートでした。
![Oodles アプリの Lighthouse レポート](https://web.dev/static/articles/web-performance-made-easy/image/lighthouse-report-oodles-04ce89ae09ebc.png?hl=ja)
Lighthouse レポートに表示されるアプリの最初のパフォーマンスは非常に悪かったです。3G ネットワークでは、最初の有意なペイント、つまりアプリがインタラクティブになるまで 15 秒間待たなければなりませんでした。Lighthouse は、サイトの問題を大量に検出しました。全体的なパフォーマンス スコアは 23 で、そのことを如実に反映しています。
ページの重量は約 3.4 MB で、削減が急務でした。
これが、パフォーマンスに関する最初の課題の始まりでした。全体的なエクスペリエンスに影響を与えることなく、簡単に削除できるものを探すことです。
パフォーマンスの最適化案
不要なリソースを削除する
空白文字とコメントは、安全に削除できる明らかなものです。
![圧縮によるメリット](https://web.dev/static/articles/web-performance-made-easy/image/gains-minification-209064021d2a2.png?hl=ja)
Lighthouse の未圧縮の CSS と JavaScript の監査で、この改善案がハイライト表示されます。ビルドプロセスに webpack を使用していたため、圧縮を行うには Uglify JS プラグインを使用しました。
圧縮は一般的なタスクであるため、使用しているビルドプロセスに応じた既製のソリューションを探すことができます。
この分野で役立つ別の監査は、テキスト圧縮を有効にするです。圧縮されていないファイルを送信する理由はありません。ほとんどの CDN は、これを標準でサポートしています。
コードのホストには Firebase Hosting を使用していました。Firebase ではデフォルトで gzipping が有効になっているため、リーズナブルな CDN にコードをホストするだけで、この機能が無料で利用できました。
gzip は非常に一般的な圧縮方法ですが、Zopfli や Brotli などの他のメカニズムも注目を集めています。Brotli はほとんどのブラウザでサポートされています。バイナリを使用して、アセットをサーバーに送信する前に事前に圧縮できます。
効率的なキャッシュ ポリシーを使用する
次のステップは、不要なリソースを 2 回送信しないようにすることです。
Lighthouse の非効率的なキャッシュ ポリシーの監査により、まさにそれを実現するためにキャッシュ戦略を最適化できることに気付きました。サーバーに max-age 有効期限ヘッダーを設定することで、ユーザーが繰り返しアクセスしたときに、以前にダウンロードしたリソースを再利用できるようにしました。
理想的には、できるだけ多くのリソースをできるだけ長い期間安全にキャッシュに保存し、更新されたリソースを効率的に再検証するための検証トークンを提供する必要があります。
使用されていないコードを削除する
ここまでは、不要なダウンロードの明らかな部分を削除してきましたが、それほど明らかでない部分はどうでしょうか。たとえば、未使用のコードです。
![DevTools のコード カバレッジ](https://web.dev/static/articles/web-performance-made-easy/image/code-coverage-devtools-d9d9ad4c8416d.png?hl=ja)
アプリに、実際には必要のないコードが含まれていることがあります。これは、アプリの開発に長い期間を要する場合や、チームや依存関係が変更された場合に特に発生します。また、孤立したライブラリが残されることもあります。まさにこの状況です。
最初は、マテリアル コンポーネント ライブラリを使用してアプリのプロトタイプをすばやく作成していましたが、カスタム ルック&フィールに移行したため、そのライブラリは完全に忘れてしまいました。幸い、コードカバレッジ チェックにより、バンドルで再発見できました。
コード カバレッジの統計情報は、DevTools でアプリケーションの実行時間と読み込み時間の両方について確認できます。下のスクリーンショットには、2 つの大きな赤いストライプがあります。CSS の 95% 以上が未使用で、JavaScript も大量に未使用でした。
Lighthouse でも、未使用の CSS ルールの監査でこの問題が検出されました。400 KB 以上の削減が見込まれます。コードに戻り、そのライブラリの JavaScript と CSS の両方を削除しました。
![MVC アダプターを削除すると、スタイルが 10 KB に減少](https://web.dev/static/articles/web-performance-made-easy/image/if-drop-mvc-adapter-sty-f311da23542ff.png?hl=ja)
これにより、CSS バンドルが 20 倍小さくなりました。これは、2 行の短い commit としては非常に良い結果です。
もちろん、パフォーマンス スコアは向上し、Time to Interactive も大幅に改善されました。
ただし、このような変更では、指標とスコアを確認するだけでは十分ではありません。実際のコードを取り除くことはリスクが伴うため、潜在的なリグレッションには常に注意する必要があります。
コードの 95% は使用されていませんでしたが、どこかに 5% 残っています。あるコンポーネントが、そのライブラリのスタイル(塗り絵スライダーの小さな矢印)をまだ使用していたようです。ただし、変更はごく小さなものだったため、手動でスタイルをボタンに組み込むことができました。
![ライブラリがないためボタンが機能しない](https://web.dev/static/articles/web-performance-made-easy/image/buttons-got-broken-missi-6e2d05b1a4f04.png?hl=ja)
コードを削除する場合は、視覚的なリグレッションの可能性を防ぐために、適切なテスト ワークフローが確立されていることを確認してください。
過大なネットワーク ペイロードの回避
大きなリソースはウェブページの読み込みを遅らせる可能性があることは認識しております。ユーザーの費用やデータプランに大きな影響を与える可能性があるため、この点に注意することが非常に重要です。
Lighthouse は、巨大なネットワーク ペイロードの監査を使用して、一部のネットワーク ペイロードに問題があることを検出しました。
![過大なネットワーク ペイロードを検出する](https://web.dev/static/articles/web-performance-made-easy/image/detect-enormous-network-p-b417c0f85336d.png?hl=ja)
ここでは、3 MB を超えるコードが配布されていることがわかりました。これは、特にモバイルでは非常に大きな量です。
このリストの一番上には、圧縮されていないコードが 2 MB の JavaScript ベンダー バンドルがあることが Lighthouse によってハイライト表示されています。これは webpack でも問題として指摘されています。
よく言われるように、リクエストを送信しないことが最速のリクエストです。
理想的には、ユーザーに配信するすべてのアセットの価値を測定し、それらのアセットのパフォーマンスを測定し、最初のエクスペリエンスで実際に配信する価値があるかどうかを判断する必要があります。これらのアセットは、デフォルトでは遅延読み込み、遅延読み込み、アイドル状態のときに処理されることがあります。
Google の場合は、JavaScript バンドルが大量に存在するため、JavaScript コミュニティに豊富な JavaScript バンドル監査ツールが存在するという幸運に恵まれました。
![JavaScript バンドルの監査](https://web.dev/static/articles/web-performance-made-easy/image/javascript-bundle-auditin-bb72c40c2152f.png?hl=ja)
まず webpack バンドル アナライザを実行しました。このツールは、解析された JavaScript が 1.6 MB の unicode という依存関係が含まれていることを教えてくれました。これはかなりの量です。
その後、エディタに移動し、Visual Code の Import Cost プラグインを使用して、インポートするすべてのモジュールの費用を可視化できました。これにより、このモジュールを参照しているコードを含むコンポーネントを特定できました。
その後、別のツールである BundlePhobia に切り替えました。これは、任意の NPM パッケージの名前を入力して、圧縮後のサイズを実際に確認できるツールです。使用していたスラグ モジュールの代替として、2.2 KB しかないモジュールを見つけたので、そちらに切り替えました。
これはパフォーマンスに大きな影響を与えました。この変更と、JavaScript バンドルのサイズを削減できる他の機会の発見により、2.1 MB のコードが削減されました。
これらのバンドルの gzip 圧縮と圧縮後のサイズを考慮すると、全体で 65% の改善が見られました。プロセスとして行う価値があることがわかりました。
そのため、一般的に、サイトやアプリで不要なダウンロードを排除するようにしてください。アセットのインベントリを作成し、パフォーマンスへの影響を測定すると、大きな違いが生じる可能性があります。そのため、アセットを定期的に監査してください。
コード分割による JavaScript の起動時間の短縮
ネットワーク ペイロードが大きいとアプリに大きな影響を与えますが、JavaScript も大きな影響を与える可能性があります。
JavaScript は最も費用のかかるアセットです。モバイルで JavaScript の大きなバンドルを送信すると、ユーザーがユーザー インターフェース コンポーネントを操作できるようになるまでの時間が長くなる可能性があります。つまり、実際には何も意味のない操作を UI 上で行っている可能性があります。そのため、JavaScript の費用がこれほど高くなる理由を理解することが重要です。
ブラウザが JavaScript を処理する仕組みは次のとおりです。
![JavaScript の処理](https://web.dev/static/articles/web-performance-made-easy/image/javascript-processing-a88df8122641b.png?hl=ja)
まず、そのスクリプトをダウンロードする必要があります。JavaScript エンジンがそのコードを解析し、コンパイルして実行する必要があります。
これらのフェーズは、デスクトップ マシンやノートパソコン、ハイエンド スマートフォンなどのハイエンド デバイスではそれほど時間がかかりません。ただし、平均的なスマートフォンでは、このプロセスに 5 ~ 10 倍の時間がかかることがあります。これがインタラクティビティの遅延の原因となるため、この時間を短縮することが重要です。
アプリでこのような問題を検出できるように、Lighthouse に新しい JavaScript 起動時間の監査を導入しました。
![JavaScript の起動時間](https://web.dev/static/articles/web-performance-made-easy/image/javascript-boot-time-d9ae37a556e82.png?hl=ja)
Oodle アプリの場合、JavaScript の起動に 1.8 秒かかったことがわかります。すべてのルートとコンポーネントを 1 つのモノリシックな JavaScript バンドルに静的にインポートしていました。
この問題を回避する方法の一つが、コード分割を使用することです。
![コード分割はピザのようなものです](https://web.dev/static/articles/web-performance-made-easy/image/code-splitting-is-pizza-6008484e57adc.png?hl=ja)
コード分割とは、ユーザーにピザ全体分の JavaScript を提供するのではなく、必要に応じて一度に 1 スライスだけ提供するという考え方です。
コード分割は、ルートレベルまたはコンポーネント レベルで適用できます。React や React Loadable、Vue.js、Angular、Polymer、Preact などの複数のライブラリと組み合わせて使用できます。
コード分割をアプリに組み込み、静的インポートから動的インポートに切り替えることで、必要に応じてコードを非同期で遅延読み込みできるようになりました。
![動的インポートによるコード分割](https://web.dev/static/articles/web-performance-made-easy/image/code-splitting-dynamic-i-bef50644cc8ac.png?hl=ja)
これにより、バンドルのサイズが縮小され、JavaScript の起動時間が短縮されました。0.78 秒に短縮され、アプリの速度が 56% 向上しました。
一般に、JavaScript を多用するエクスペリエンスを構築する場合は、ユーザーに必要なコードのみを送信してください。
コード分割などのコンセプトを利用し、ツリー シェイキングなどのアイデアを検討します。また、webpack を使用している場合は、webpack-libs-optimizations リポジトリで、ライブラリのサイズを削減する方法に関するアイデアをいくつか確認してください。
画像を最適化する
![画像の読み込みパフォーマンスに関するジョーク](https://web.dev/static/articles/web-performance-made-easy/image/image-loading-performance-82f3792c437f6.png?hl=ja)
Oodle アプリでは、多くの画像を使用しています。残念ながら、Lighthouse は Google ほど熱心ではありませんでした。実際、画像関連の 3 つの監査ですべて不合格でした。
画像の最適化を忘れた、画像のサイズが正しくない、他の画像形式を使用することで改善できる、などの理由が考えられます。
![画像監査](https://web.dev/static/articles/web-performance-made-easy/image/image-audits-719c8447f8aaf.png?hl=ja)
まず、画像の最適化から始めました。
1 回限りの最適化ラウンドには、ImageOptim や XNConvert などのビジュアル ツールを使用できます。
より自動化されたアプローチでは、imagemin などのライブラリを使用して、ビルドプロセスに画像最適化ステップを追加します。
これにより、今後追加される画像が自動的に最適化されます。Akamai などの CDN や、Cloudinary、Fastly、Uploadcare などのサードパーティ ソリューションは、包括的な画像最適化ソリューションを提供しています。これらのサービスに画像をホストすることもできます。
費用やレイテンシの問題でそうしたくない場合は、Thumbor や Imageflow などのプロジェクトでセルフホスト型の代替手段を利用できます。
![最適化前と最適化後](https://web.dev/static/articles/web-performance-made-easy/image/before-after-optimizatio-45b3bbf20acca.png?hl=ja)
背景の PNG は、webpack でサイズが大きいと報告されました。これは当然のことでした。ビューポートに合わせてサイズを調整し、ImageOptim で実行した結果、100 KB まで削減できました。これは許容範囲内です。
サイト上の複数の画像に対してこの作業を繰り返すことで、ページ全体の重量を大幅に削減できました。
アニメーション コンテンツに適した形式を使用する
GIF は非常に高額になる場合があります。驚くべきことに、GIF 形式はそもそもアニメーション プラットフォームとして意図されたものではありません。そのため、より適切な動画形式に切り替えると、ファイルサイズを大幅に削減できます。
Oodle アプリでは、ホームページの導入シーケンスとして GIF を使用していました。Lighthouse によると、より効率的な動画形式に切り替えることで、7 MB 以上節約できる可能性があります。クリップの重量は約 7.3 MB で、一般的なウェブサイトには大きすぎます。そのため、2 つのソースファイル(mp4 と WebM)を使用して動画要素に変換し、幅広いブラウザでサポートできるようにしました。
![アニメーション GIF を動画に置き換える](https://web.dev/static/articles/web-performance-made-easy/image/replace-animated-gifs-vi-fc084e0a3fb4e.png?hl=ja)
FFmpeg ツールを使用して、アニメーション GIF を mp4 ファイルに変換しました。WebM 形式にすると、さらにサイズを削減できます。ImageOptim API を使用すると、このような変換を自動的に行えます。
ffmpeg -i animation.gif -b:v 0 -crf 40 -vf scale=600:-1 video.mp4
この変換により、全体の重量を 80% 以上削減できました。これにより、サイズは約 1 MB になりました。
それでも、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=preconnect
、preload
、prefetch
などのリソース ヒントなど、この問題の解決に役立つ多くの機能を追加してきました。
ウェブ プラットフォームに導入されたこれらの機能は、ブラウザが適切なタイミングで適切なものを取得するのに役立ちます。また、スクリプトを使用するカスタム読み込みやロジックベースのアプローチよりも効率的です。
Lighthouse がこれらの機能を効果的に使用するためのガイダンスを実際に提供している方法を見てみましょう。
Lighthouse が最初に提案するのは、送信元への複数の費用のかかる往復を回避することです。
![送信元への複数の往復を回避し、費用を削減](https://web.dev/static/articles/web-performance-made-easy/image/avoid-multiple-costly-ro-1349e14da4d4d.png?hl=ja)
Oodle アプリの場合は、実際に Google Fonts を多用しています。Google フォント スタイルシートをページに配置するたびに、最大 2 つのサブドメインが接続されます。Lighthouse は、この接続をウォームアップできれば、最初の接続時間を最大 300 ミリ秒短縮できると示しています。
link rel preconnect を利用することで、この接続レイテンシを効果的にマスクできます。
特に、Google フォントのような、フォントフェイスの CSS が googleapis.com でホストされ、フォント リソースが Gstatic でホストされている場合、これは非常に大きな影響を与える可能性があります。この最適化を適用した結果、数百ミリ秒の短縮に成功しました。
Lighthouse は次に、主要なリクエストをプリロードすることを提案します。
![プリロード鍵リクエスト](https://web.dev/static/articles/web-performance-made-easy/image/preload-key-requests-a2751a962b7e2.png?hl=ja)
<link rel=preload>
は非常に強力で、現在のナビゲーションの一部としてリソースが必要であることをブラウザに通知し、ブラウザがリソースをできるだけ早く取得できるようにします。
Lighthouse は、2 つのウェブフォントが読み込まれているため、重要なウェブフォント リソースをプリロードする必要があることを示しています。
ウェブフォントでプリロードする方法は次のとおりです。rel=preload
を指定して、フォントタイプとともに as
を渡し、読み込むフォントタイプ(woff2 など)を指定します。
これはページに非常に大きな影響を与える可能性があります。
![リソースのプリロードの影響](https://web.dev/static/articles/web-performance-made-easy/image/impact-preloading-resour-d6cf8908f75e3.png?hl=ja)
通常、link rel preload を使用せずに、ウェブフォントがページにとって重要である場合、ブラウザはまず HTML を取得し、CSS を解析し、その後でウェブフォントを取りにいきます。
link rel preload を使用すると、ブラウザが HTML を解析するとすぐに、ウェブフォント取得を開始できます。アプリの場合、ウェブフォントを使用してテキストをレンダリングする時間を 1 秒短縮できました。
Google Fonts を使用してフォントをプリロードしようとすると、1 つ注意点があります。
スタイルシートのフォントフェイスに指定する Google フォント URL は、フォント チームがかなり定期的に更新しているものです。これらの URL は期限切れになるか、定期的に更新される可能性があります。そのため、フォント読み込みを完全に制御したい場合は、ウェブフォントをセルフホストすることをおすすめします。これにより、リンク rel プリロードなどの機能にアクセスできるため、非常に便利です。
弊社の場合、Google ウェブフォント ヘルパーというツールが、一部のウェブフォントをオフラインにしてローカルに設定するのに非常に役立ちました。このツールもぜひご確認ください。
重要なリソースの一部としてウェブフォントを使用している場合でも、JavaScript を使用している場合でも、ブラウザが重要なリソースをできるだけ早く配信できるようにしてください。
試験運用版: 優先度ヒント
本日は特別な情報をお知らせします。リソース ヒントやプリロードなどの機能に加えて、Google は優先度ヒントというまったく新しい試験運用版のブラウザ機能の開発に取り組んでいます。
![最初に表示されるコンテンツの優先度を設定する](https://web.dev/static/articles/web-performance-made-easy/image/set-priority-the-initial-a002f3faeabf3.png?hl=ja)
これは、リソースの重要度をブラウザにヒントとして伝えることができる新機能です。新しい属性 importance が公開され、値は low、high、auto です。
これにより、競合を減らすために、重要でないリソース(クリティカルでないスタイル、画像、フェッチ API 呼び出しなど)の優先度を下げることができます。ヘッダー画像など、より重要な要素の優先度を上げることもできます。
Oodle アプリの場合、この分析結果から、実際に最適化できる場所が 1 つ見つかりました。
![最初に表示されるコンテンツの優先度を設定する](https://web.dev/static/articles/web-performance-made-easy/image/set-priority-the-initial-b31819a78b75c.png?hl=ja)
画像に遅延読み込みを追加する前は、ブラウザはすべてのドゥードルが含まれる画像カルーセルを表示し、カルーセルの一番最初にすべての画像を優先度高く取得していました。残念ながら、ユーザーにとって最も重要な画像はカルーセルの中央にありました。そこで、背景画像の重要度を非常に低く、前景画像の重要度を非常に高く設定しました。これにより、遅い 3G で 2 秒の差が生まれ、画像の取得とレンダリングの速度が向上しました。良い経験になりました。
この機能は数週間以内に Canary に導入される予定です。
ウェブフォント読み込み戦略を準備する
タイポグラフィは優れたデザインの基本です。ウェブフォントを使用している場合は、テキストのレンダリングをブロックしないことが理想的です。また、テキストを非表示にすることは絶対に避けてください。
この問題は、Lighthouse のWeb フォント読み込み中の非表示テキストを回避する監査でハイライト表示されます。
![Web フォント読み込み中のテキストの非表示を回避する](https://web.dev/static/articles/web-performance-made-easy/image/avoid-invisible-text-whil-d461292533245.png?hl=ja)
フォントフェイス ブロックを使用してウェブフォントを読み込む場合は、そのウェブフォントの取得に時間がかかる場合にどうするかをブラウザに決定させます。一部のブラウザでは、この処理が完了するまで最大 3 秒間待機してからシステム フォントに戻り、フォントがダウンロードされると、最終的にそのフォントに入れ替えます。
Google は、この見えないテキストを回避しようとしています。この場合、ウェブフォントが読み込みに時間がかかりすぎたため、今週のクラシックな 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');
}
フォント表示を使用すると、ウェブフォントのスワップにかかる時間に基づいて、レンダリング方法やフォールバック方法を決定できます。
この例では、フォント表示の入れ替えを使用しています。スワップでは、フォントフェイスのブロック期間は 0 秒で、スワップ期間は無限になります。つまり、フォントが読み込まれるまでに時間がかかる場合は、ブラウザはすぐにフォールバック フォントでテキストを描画します。フォント フェイスが利用可能になると、フォント フェイスが入れ替わります。
アプリの場合、これは非常に早い段階で意味のあるテキストを表示し、準備ができたらウェブフォントへと移行できたため、非常に便利でした。
![フォント表示の結果](https://web.dev/static/articles/web-performance-made-easy/image/font-display-outcome-a014081404b38.png?hl=ja)
ウェブの大部分で使用されているウェブフォントを使用している場合は、適切なウェブフォント読み込み戦略を用意してください。
フォントの読み込みエクスペリエンスを最適化するために使用できるウェブ プラットフォームの機能はたくさんありますが、Zach Leatherman の Web Font Recipes リポジトリもぜひご覧ください。
レンダリングを妨げるスクリプトを減らす
ダウンロード チェーンの早い段階でプッシュできるアプリの他の部分があり、少なくとも基本的なユーザー エクスペリエンスを少し早く提供できます。
Lighthouse のタイムライン ストリップでは、すべてのリソースが読み込まれている最初の数秒間は、ユーザーがコンテンツを実際に見ることができないことがわかります。
![レンダリングを妨げるスタイルシートの機会を減らす](https://web.dev/static/articles/web-performance-made-easy/image/reduce-render-blocking-st-ee605dfe41336.png?hl=ja)
外部スタイルシートのダウンロードと処理により、レンダリング プロセスが進まない。
一部のスタイルを少し早めに配信することで、重要なレンダリング パスを最適化できます。
この初期レンダリングを担当するスタイルを抽出して HTML にインライン化すると、ブラウザは外部スタイルシートの到着を待たずにすぐにレンダリングできます。
この例では、Critical という NPM モジュールを使用して、ビルドステップ中に重要なコンテンツを index.html にインライン化しました。
このモジュールは、ほとんどの作業を自動化してくれますが、さまざまなルートでスムーズに動作させるには、少し工夫が必要です。
注意を払わない場合や、サイト構造が非常に複雑な場合、最初からアプリシェル アーキテクチャを計画していないと、このタイプのパターンを導入するのは非常に困難になる可能性があります。
そのため、早い段階でパフォーマンスを考慮することが重要です。最初からパフォーマンスを重視して設計しないと、後で問題が発生する可能性が高くなります。
最終的に、リスクを冒した甲斐があり、うまく機能し、アプリはコンテンツの配信を大幅に早め、最初の意味のあるペイント時間を大幅に短縮できました。
結果
以上、サイトに適用したパフォーマンス最適化の一覧です。結果を見てみましょう。3G ネットワーク上の中程度のモバイル デバイスで、最適化前と最適化後のアプリの読み込み時間は次のとおりです。
Lighthouse のパフォーマンス スコアは 23 から 91 に上昇しました。速度の面ではかなりの進歩です。すべての変更は、Lighthouse レポートを継続的に確認し、それに沿って行われました。すべての改善が技術的にどのように実装されたかを確認したい場合は、リポジトリ、特にそこに配置された PR をご覧ください。
予測パフォーマンス - データドリブンのユーザー エクスペリエンス
Google は、機械学習が多くの分野で将来の大きな可能性を秘めていると考えています。今後、より多くのテストを促進したいと考えているアイデアのひとつは、実際のデータが Google が作成するユーザー エクスペリエンスを本当にガイドできるということです。
現在、Google は、ユーザーが望むものや必要とするものを、つまりプリフェッチ、プリロード、プリキャッシュに値するものを、恣意的に判断しています。推測が正しければ、少量のリソースを優先できますが、ウェブサイト全体にスケーリングするのは非常に困難です。
実は、最適化に役立つデータはすでに利用可能です。Google アナリティクス Reporting API を使用すると、サイト上の任意の URL の次に多いページと離脱率を確認できるため、優先すべきリソースを判断できます。
これを優れた確率モデルと組み合わせることで、コンテンツを積極的に過剰プリフェッチしてユーザーのデータを無駄にすることを回避できます。このようなモデルを実装するには、Google アナリティクスのデータを利用し、機械学習とマルコフ連鎖やニューラル ネットワークなどのモデルを使用します。
![ウェブアプリ用データドリブン バンドル](https://web.dev/static/articles/web-performance-made-easy/image/data-driven-bundling-web-3843c496c6e42.png?hl=ja)
このテストを容易に実施できるように、Guess.js という新しいイニシアチブを発表いたします。
![Guess.js](https://web.dev/static/articles/web-performance-made-easy/image/guessjs-8f7d906237584.png?hl=ja)
Guess.js は、ウェブのデータドリブンなユーザー エクスペリエンスに重点を置いたプロジェクトです。データを使用してウェブのパフォーマンスを改善し、さらにその先に進むためのヒントとしてお役立ていただければ幸いです。すべてオープンソースであり、現在 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、Yusuke Utsunomiya、Tom Ankers、Lighthouse、Google Doodles に感謝します。