フロントエンドパフォーマンスチェックリスト2021(PDF、Apple Pages、MS Word)

公開: 2022-03-10
簡単なまとめ↬2021を…速くしましょう! 毎年恒例のフロントエンドパフォーマンスチェックリスト(PDF、Apple Pages、MS Wordとして入手可能)。メトリックからツール、フロントエンドテクニックまで、今日のWebで高速なエクスペリエンスを作成するために知っておく必要のあるすべてが含まれています。 2016年から更新されています。ああ、メールマガジンで役立つフロントエンドのヒントを入手することもできます。

Webパフォーマンスはトリッキーな獣ですね。 パフォーマンスの観点から自分がどこに立っているかを実際にどのように知ることができますか?また、パフォーマンスのボトルネックは正確には何ですか? 高価なJavaScript、遅いWebフォントの配信、重い画像、または遅いレンダリングですか? ツリーシェーキング、スコープホイスト、コード分割、および交差オブザーバー、プログレッシブハイドレーション、クライアントヒント、HTTP / 3、サービスワーカー、およびエッジワーカーを使用したすべての派手な読み込みパターンで十分に最適化されましたか? そして、最も重要なことは、パフォーマンスの向上をどこから始めればよいのでしょうか。また、パフォーマンス文化を長期的に確立するにはどうすればよいのでしょうか。

当時、パフォーマンスは単なる後付けでした。 多くの場合、プロジェクトの最後まで延期され、縮小、連結、資産の最適化、およびサーバーのconfigファイルのいくつかの微調整に要約されます。 今振り返ると、物事はかなり大きく変わったようです。

パフォーマンスは技術的な問題だけではありません。アクセシビリティからユーザビリティ、検索エンジン最適化に至るまですべてに影響します。ワークフローに組み込む場合、設計上の決定はパフォーマンスへの影響によって通知される必要があります。 パフォーマンスは継続的に測定、監視、改善する必要があり、Webの複雑さが増すと、デバイス、ブラウザ、プロトコル、ネットワークタイプ、レイテンシによってデータが大幅に異なるため、メトリックの追跡が困難になる新しい課題が発生します( CDN、ISP、キャッシュ、プロキシ、ファイアウォール、ロードバランサー、サーバーはすべてパフォーマンスに影響します)。

したがって、プロジェクトの開始からWebサイトの最終リリースまで、パフォーマンスを向上させる際に留意しなければならないすべてのことの概要を作成した場合、それはどのようになりますか? 以下に、2021年の(できれば公平で客観的な)フロントエンドパフォーマンスチェックリストを示します。これは、応答時間が速く、ユーザーインタラクションがスムーズで、サイトがスムーズでないことを確認するために考慮する必要のある問題の最新の概要です。ユーザーの帯域幅を使い果たします。

目次

  • すべて別のページに
  • 準備:計画と指標
    パフォーマンス文化、コアWebバイタル、パフォーマンスプロファイル、CrUX、Lighthouse、FID、TTI、CLS、デバイス。
  • 現実的な目標の設定
    パフォーマンスバジェット、パフォーマンス目標、RAILフレームワーク、170KB / 30KBバジェット。
  • 環境の定義
    フレームワーク、ベースラインパフォーマンスコスト、Webpack、依存関係、CDN、フロントエンドアーキテクチャ、CSR、SSR、CSR + SSR、静的レンダリング、事前レンダリング、PRPLパターンの選択。
  • 資産の最適化
    Brotli、AVIF、WebP、レスポンシブ画像、AV1、アダプティブメディアローディング、ビデオ圧縮、Webフォント、Googleフォント。
  • ビルドの最適化
    JavaScriptモジュール、モジュール/モジュールなしパターン、ツリーシェイク、コード分割、スコープホイスト、Webpack、ディファレンシャルサービング、Webワーカー、WebAssembly、JavaScriptバンドル、React、SPA、部分的なハイドレーション、相互作用のインポート、サードパーティ、キャッシュ。
  • 配信の最適化
    遅延読み込み、交差オブザーバー、レンダリングとデコードの延期、重要なCSS、ストリーミング、リソースヒント、レイアウトシフト、サービスワーカー。
  • ネットワーキング、HTTP / 2、HTTP / 3
    OCSPステープリング、EV / DV証明書、パッケージング、IPv6、QUIC、HTTP / 3。
  • テストとモニタリング
    監査ワークフロー、プロキシブラウザ、404ページ、GDPR Cookie同意プロンプト、パフォーマンス診断CSS、アクセシビリティ。
  • クイックウィン
  • チェックリストをダウンロードする(PDF、Apple Pages、MS Word)
  • オフウィーゴー!

(チェックリストPDF(166 KB)をダウンロードするか、編集可能なApple Pagesファイル(275 KB)または.docxファイル(151 KB)をダウンロードすることもできます。

準備:計画と指標

マイクロ最適化はパフォーマンスを軌道に乗せるのに最適ですが、明確に定義された目標を念頭に置くことが重要です。これは、プロセス全体で行われる決定に影響を与える測定可能な目標です。 いくつかの異なるモデルがあり、以下で説明するモデルはかなり意見が分かれています。早い段階で独自の優先順位を設定してください。

  1. パフォーマンス文化を確立します。
    多くの組織では、フロントエンド開発者は、根本的な一般的な問題が何であるか、およびそれらを修正するためにどの戦略を使用する必要があるかを正確に知っています。 ただし、パフォーマンスカルチャーの確立された承認がない限り、各決定は部門の戦場になり、組織をサイロに分割します。 ビジネスの利害関係者の賛同が必要であり、それを取得するには、ケーススタディ、または速度(特に、後で詳しく説明するコアWebバイタル)がメトリックと主要業績評価指標にどのように役立つかについての概念実証を確立する必要があります。 ( KPI )彼らは気にします。

    たとえば、パフォーマンスをより具体的にするために、コンバージョン率とアプリケーションの負荷までの時間の相関関係、およびレンダリングパフォーマンスを示すことで、収益パフォーマンスへの影響を明らかにすることができます。 または、検索ボットのクロール率(PDF、27〜50ページ)。

    開発/設計チームとビジネス/マーケティングチームの間に強力な連携がなければ、パフォーマンスは長期的に維持されません。 カスタマーサービスとセールスチームに寄せられる一般的な苦情を調査し​​、高いバウンス率とコンバージョンの低下に関する分析を調査します。 パフォーマンスの向上がこれらの一般的な問題のいくつかを軽減するのにどのように役立つかを探ります。 話している利害関係者のグループに応じて、議論を調整します。

    モバイルとデスクトップの両方で(たとえば、Google Analyticsを使用して)パフォーマンス実験を実行し、結果を測定します。 これは、実際のデータを使用して会社に合わせたケーススタディを構築するのに役立ちます。 さらに、WPO Statsで公開されたケーススタディと実験のデータを使用すると、パフォーマンスが重要である理由、およびパフォーマンスがユーザーエクスペリエンスとビジネスメトリックにどのような影響を与えるかについて、ビジネスの感度を高めるのに役立ちます。 ただし、パフォーマンスだけが重要であると述べるだけでは不十分です。測定可能で追跡可能な目標を設定し、それらを長期にわたって観察する必要もあります。

    そこに着く方法? 長期的なパフォーマンスの構築に関する彼女の講演で、Allison McKnightは、Etsyでのパフォーマンス文化の確立にどのように貢献したかについての包括的なケーススタディを共有しています(スライド)。 最近では、タミー・エヴァーツが、小規模組織と大規模組織の両方で非常に効果的なパフォーマンスチームの習慣について話しました。

    組織でこれらの会話をしている間、UXがさまざまなエクスペリエンスであるように、Webパフォーマンスは分散であることに留意することが重要です。 Karolina Szczurが指摘したように、「単一の数値が目指すべき評価を提供できると期待することは、欠陥のある仮定です」。 したがって、パフォーマンスの目標は、きめ細かく、追跡可能で、具体的である必要があります。

モバイルでは、セッションごとに、読み込み時間が速いユーザーは平均より17%多くの収益をもたらします
モバイルでは、セッションごとに、読み込み時間が速いユーザーは平均より17%多くの収益をもたらします。 (Addy OsmaniによるWebパフォーマンスの影響)
単一の数値が目指すべき評価を提供できることを期待することは、欠陥のある仮定です
単一の数値が目指すべき評価を提供できると期待することは、欠陥のある仮定です。 (画像クレジット:パフォーマンスはKarolina Czczurによる配布です)
  1. 目標:最速の競合他社よりも少なくとも20%速くなります。
    心理学の調査によると、自分のWebサイトが競合他社のWebサイトよりも高速であるとユーザーに感じてもらいたい場合は、少なくとも20%高速である必要があります。 主な競合他社を調査し、モバイルとデスクトップでのパフォーマンスに関する指標を収集し、競合他社を上回るのに役立つしきい値を設定します。 ただし、正確な結果と目標を得るには、まず分析を調べて、ユーザーのエクスペリエンスの全体像を把握するようにしてください。 次に、90パーセンタイルのテストの経験を模倣できます。

    競合他社のパフォーマンスの第一印象を良くするために、Chrome UXレポート( CrUX 、既製のRUMデータセット、Ilya Grigorikによるビデオ紹介、Rick Viscomiによる詳細ガイド)、またはRUM監視ツールであるTreoを使用できます。 ChromeUXレポートを利用しています。 データはChromeブラウザのユーザーから収集されるため、レポートはChrome固有のものになりますが、さまざまな訪問者にパフォーマンス、最も重要なのはCore WebVitalsスコアをかなり完全に分散させることができます。 新しいCrUXデータセットは、毎月第2火曜日にリリースされることに注意してください。

    または、次を使用することもできます。

    • AddyOsmaniのChromeUXレポート比較ツール、
    • スピードスコアカード(収益への影響の見積もりも提供します)、
    • 実際のユーザーエクスペリエンステストの比較または
    • SiteSpeed CI(合成テストに基づく)。

    :Page SpeedInsightsまたはPageSpeed Insights APIを使用している場合(非推奨ではありません!)、集計だけでなく、特定のページのCrUXパフォーマンスデータを取得できます。 このデータは、「ランディングページ」や「商品リスト」などのアセットのパフォーマンス目標を設定するのに非常に役立ちます。 また、CIを使用して予算をテストしている場合、ターゲットの設定にCrUXを使用した場合は、テストした環境がCrUXと一致することを確認する必要があります( Patrick Meenanに感謝します)。

    速度の優先順位付けの背後にある理由を示すために何らかの支援が必要な場合、またはパフォーマンスの低下に伴うコンバージョン率の低下またはバウンス率の増加を視覚化したい場合、あるいは組織内のRUMソリューションを提唱する必要がある場合はSergey Chernyshevは、UX Speed Calculatorを構築しました。これは、データをシミュレートして視覚化し、ポイントを推進するのに役立つオープンソースツールです。

    CrUXは、Google Chromeユーザーから収集されたトラフィックを使用して、時間の経過に伴うパフォーマンス分布の概要を生成します
    CrUXは、Google Chromeユーザーから収集されたトラフィックを使用して、時間の経過に伴うパフォーマンス分布の概要を生成します。 ChromeUXダッシュボードで独自に作成できます。 (大プレビュー)
    ポイントを推進するためにパフォーマンスを主張する必要がある場合:UX Speed Calculatorは、実際のデータに基づいて、バウンス率、コンバージョン、総収益に対するパフォーマンスの影響を視覚化します
    ポイントを推進するためにパフォーマンスを主張する必要がある場合:UX Speed Calculatorは、実際のデータに基づいて、バウンス率、コンバージョン、総収益に対するパフォーマンスの影響を視覚化します。 (大プレビュー)

    CrUXからのデータを、速度低下、盲点、非効率性が存在する場所で、競合他社やプロジェクトのために、すでに迅速に解決する必要のある他のデータと組み合わせて、もう少し深く掘り下げたい場合があります。 彼の仕事では、ハリー・ロバーツはサイトスピード地形スプレッドシートを使用しており、これを使用して主要なページタイプごとにパフォーマンスを分類し、それらの間でさまざまな主要なメトリックがどのようにあるかを追跡しています。 スプレッドシートは、Googleスプレッドシート、Excel、OpenOfficeドキュメント、またはCSVとしてダウンロードできます。

    サイトの主要なページに表示される主要なメトリックを使用したサイト速度の地形
    サイトの主要なページに表される主要なメトリックを使用したサイト速度の地形。 (大プレビュー)

    また、最後までやりたい場合は、サイトのすべてのページで(Lightouse Paradeを介して)Lighthouseパフォーマンス監査を実行し、出力をCSVとして保存できます。 これは、競合他社のどの特定のページ(またはページの種類)のパフォーマンスが悪いか良いか、そして何に集中したいかを特定するのに役立ちます。 (自分のサイトの場合は、分析エンドポイントにデータを送信する方がおそらく良いでしょう!)

    Lighthouse Paradeを使用すると、サイトのすべてのページでLighthouseパフォーマンス監査を実行し、出力をCSVとして保存できます。
    Lighthouse Paradeを使用すると、サイトのすべてのページでLighthouseパフォーマンス監査を実行し、出力をCSVとして保存できます。 (大プレビュー)

    データを収集し、スプレッドシートを設定し、20%削減し、この方法で目標(パフォーマンス予算)を設定します。 これで、テストするための測定可能なものができました。 予算を念頭に置いて、対話するまでの時間を短縮するために最小限のペイロードだけを出荷しようとしている場合は、合理的な道を進んでいます。

    始めるためのリソースが必要ですか?

    • Addy Osmaniは、パフォーマンスの予算編成を開始する方法、新機能の影響を定量化する方法、および予算を超過した場合にどこから開始するかについて、非常に詳細な記事を書いています。
    • パフォーマンスバジェットを使用して設計にアプローチする方法に関するLaraHoganのガイドは、設計者に役立つ指針を提供します。
    • ハリーロバーツは、リクエストマップを使用して、パフォーマンスに対するサードパーティのスクリプトの影響を表示するGoogleスプレッドシートの設定に関するガイドを公開しました。
    • JonathanFieldingのPerformanceBudget Calculator、Katie Hempeniusのperf-budget-calculator、およびBrowser Caloriesは、予算の作成に役立ちます(Karolina Szczurの頭を上げてくれてありがとう)。
    • 多くの企業では、パフォーマンスの予算は野心的なものではなく、実際的なものである必要があり、特定のポイントを超えないようにするための保持の兆候として機能します。 その場合、過去2週間で最悪のデータポイントをしきい値として選択し、そこから取得することができます。 パフォーマンスバジェットは、それを達成するための戦略を実践的に示しています。
    • また、ビルドサイズを報告するグラフを使用してダッシュボードを設定することにより、パフォーマンスバジェットと現在のパフォーマンスの両方を表示します。 それを実現できるツールはたくさんあります。SiteSpeed.ioダッシュボード(オープンソース)、SpeedCurve、Calibreはそのほんの一部であり、perf.rocksでさらに多くのツールを見つけることができます。
    ブラウザのカロリーは、パフォーマンスの予算を設定し、ページがこれらの数値を超えているかどうかを測定するのに役立ちます。
    ブラウザのカロリーは、パフォーマンスの予算を設定し、ページがこれらの数値を超えているかどうかを測定するのに役立ちます。 (大プレビュー)

    予算を設定したら、Webpack Performance HintsとBundlesize、Lighthouse CI、PWMetrics、またはSitespeed CIを使用してビルドプロセスに組み込み、プルリクエストに予算を適用し、PRコメントでスコア履歴を提供します。

    チーム全体にパフォーマンスバジェットを公開するには、Lightwalletを介してLighthouseにパフォーマンスバジェットを統合するか、LHCIアクションを使用してGithubアクションをすばやく統合します。 また、カスタムが必要な場合は、エンドポイントのAPIであるwebpagetest-charts-apiを使用して、WebPagetestの結果からグラフを作成できます。

    ただし、パフォーマンスの認識は、パフォーマンスの予算だけから得られるべきではありません。 Pinterestと同じように、依存関係が多く、バンドルを肥大化させることがわかっているファイルやディレクトリからのインポートを禁止するカスタムeslintルールを作成できます。 チーム全体で共有できる「安全な」パッケージのリストを設定します。

    また、ビジネスにとって最も有益な重要な顧客タスクについて考えてください。 重要なアクションの許容可能な時間しきい値を調査、議論、定義し、組織全体が承認した「UX対応」のユーザータイミングマークを確立します。 多くの場合、ユーザージャーニーは多くの異なる部門の作業に影響を与えるため、許容可能なタイミングに関する調整は、今後のパフォーマンスに関する議論をサポートまたは防止するのに役立ちます。 追加されたリソースと機能の追加コストが表示され、理解されていることを確認してください。

    構築中の製品の新機能からリファクタリング、新しいグローバルオーディエンスへのリーチに至るまで、パフォーマンスへの取り組みを他の技術イニシアチブと連携させます。 したがって、さらなる開発についての会話が行われるたびに、パフォーマンスもその会話の一部になります。 コードベースが新しい場合、またはリファクタリングされている場合は、パフォーマンスの目標を達成するのがはるかに簡単です。

    また、Patrick Meenanが示唆したように、設計プロセス中にロードシーケンスとトレードオフを計画することは価値があります。 どの部分がより重要であるかを早期に優先し、それらが表示される順序を定義すると、何が遅れるかもわかります。 理想的には、その順序はCSSとJavaScriptのインポートの順序も反映するため、ビルドプロセス中のそれらの処理が容易になります。 また、ページがロードされている間(たとえば、Webフォントがまだロードされていないとき)の「中間」状態でのビジュアルエクスペリエンスを検討してください。

    組織で強力なパフォーマンス文化を確立したら、時間の経過とともに優先順位を維持するために、以前の自分よりも20%速くなることを目指します( Guy Podjarnyに感謝します)。 ただし、ボットのトラフィックと季節性の影響に加えて、顧客のさまざまなタイプと使用行動(Tobias Baldaufはケイデンスとコホートと呼んでいます)を考慮してください。

    計画、計画、計画。 早い段階でいくつかの迅速な「手に負えない果物」の最適化に取り掛かるのは魅力的かもしれません—そしてそれは迅速な勝利のための良い戦略かもしれません—しかし、現実的な会社を計画して設定することなしにパフォーマンスを優先することは非常に難しいでしょう-調整されたパフォーマンス目標。

Treo Sitesは、実際のデータに基づいた競合分析を提供します
Treoは、実際のデータに基づいた競合分析を提供します。 (大プレビュー)
2020年初頭にLighthousev6に導入された新しい指標
新しいメトリックは2020年の初めにLighthousev6に上陸しました。(大規模なプレビュー)
  1. 適切な指標を選択してください。
    すべてのメトリックが等しく重要であるわけではありません。 アプリケーションにとって最も重要なメトリックを調べます。通常、インターフェイスの最も重要なピクセルのレンダリングを開始できる速度と、レンダリングされたピクセルに入力応答性を提供できる速度によって定義されます。 この知識は、継続的な取り組みのための最良の最適化目標を提供します。 結局のところ、エクスペリエンスを定義するのはロードイベントやサーバーの応答時間ではなく、インターフェイスいかにスッキリしているのかという認識です。

    どういう意味ですか? (たとえば、 onLoadDOMContentLoadedのタイミングを介して)ページ全体の読み込み時間に焦点を合わせるのではなく、顧客が認識しているようにページの読み込みを優先します。 これは、わずかに異なる一連のメトリックに焦点を当てることを意味します。 実際、適切なメトリックを選択することは、明らかな勝者がいないプロセスです。

    TimKadlecの調査と彼の講演でのMarcosIglesiasのメモに基づいて、従来のメトリックはいくつかのセットにグループ化できます。 通常、パフォーマンスの全体像を把握するには、それらすべてが必要です。特定のケースでは、それらの一部が他よりも重要になります。

    • 数量ベースのメトリックは、リクエストの数、重み、およびパフォーマンススコアを測定します。 アラームを鳴らしたり、時間の経過とともに変化を監視したりするのには適していますが、ユーザーエクスペリエンスを理解するのにはあまり適していません。
    • マイルストーンメトリックは、読み込みプロセスの存続期間中の状態を使用します。たとえば、最初のバイトまでの時間やインタラクティブまでの時間などです。 ユーザーエクスペリエンスとモニタリングを説明するのには適していますが、マイルストーン間で何が起こっているのかを知るのにはあまり適していません。
    • レンダリングメトリックは、コンテンツのレンダリング速度の見積もりを提供します(たとえば、レンダリング開始時間、速度インデックス)。 レンダリングパフォーマンスの測定と調整には適していますが、重要なコンテンツが表示されて操作できるタイミングの測定にはあまり適していません。
    • カスタムメトリックは、ユーザーの特定のカスタムイベントを測定します。たとえば、Twitterの最初のツイートまでの時間やPinterestのPinnerWaitTimeなどです。 ユーザーエクスペリエンスを正確に説明するのには適していますが、指標をスケーリングしたり、競合他社と比較したりするのにはあまり適していません。

    全体像を完成させるために、私たちは通常、これらすべてのグループの中で有用な指標を探します。 通常、最も具体的で関連性のあるものは次のとおりです。

    • インタラクティブまでの時間(TTI)
      レイアウトが安定し、主要なWebフォントが表示され、ユーザー入力を処理するのに十分なメインスレッドが利用可能になるポイント(基本的には、ユーザーがUIを操作できる時間マーク)。 ユーザーがラグなしでサイトを使用するためにどれだけの待機を経験する必要があるかを理解するための主要なメトリック。 Boris Schapiraは、TTIを確実に測定する方法に関する詳細な投稿を書いています。
    • First Input Delay (FID) 、または入力応答性
      ユーザーが最初にサイトを操作してから、ブラウザーが実際にその操作に応答できるようになるまでの時間。 TTIを非常によく補完し、画像の欠落している部分、つまりユーザーが実際にサイトを操作したときに何が起こるかを説明します。 RUMメトリックとしてのみ意図されています。 ブラウザでFIDを測定するためのJavaScriptライブラリがあります。
    • 最大のコンテンツフルペイント(LCP)
      ページの重要なコンテンツが読み込まれた可能性が高い、ページの読み込みタイムラインのポイントをマークします。 ページの最も重要な要素は、ユーザーのビューポートに表示される最大の要素であると想定されています。 要素が折り目の上と下の両方にレンダリングされる場合、表示されている部分のみが関連性があると見なされます。
    • 合計ブロッキング時間( TBT
      ページが確実にインタラクティブになる前に、ページがどの程度非インタラクティブであるかを定量化するのに役立つメトリック(つまり、メインスレッドに50ミリ秒を超えるタスク(長いタスク)が少なくとも5秒間実行されていない)。 このメトリックは、最初のペイントから、入力の応答性を妨げるのに十分な時間メインスレッドがブロックされたInteractiveまでの時間(TTI)までの合計時間を測定します。 したがって、低いTBTが良好なパフォーマンスの良い指標であることは不思議ではありません。 (ありがとう、Artem、Phil)
    • 累積レイアウトシフト( CLS
      このメトリックは、ユーザーがサイトにアクセスするときに予期しないレイアウトシフトリフロー)を経験する頻度を強調しています。 不安定な要素と、それらが全体的なエクスペリエンスに与える影響を調べます。 スコアが低いほど良いです。
    • スピードインデックス
      ページコンテンツが視覚的に入力される速度を測定します。 スコアが低いほど良いです。 速度指数スコアは視覚的な進行速度に基づいて計算されますが、これは単なる計算値です。 また、ビューポートサイズにも影響されるため、ターゲットオーディエンスに一致するさまざまなテスト構成を定義する必要があります。 LCPがより適切なメトリックになるにつれて、重要性が低下していることに注意してください( Boris、Artemに感謝します)。
    • 費やしたCPU時間
      メインスレッドがブロックされ、ペイント、レンダリング、スクリプト作成、および読み込みに取り組んでいる頻度期間を示すメトリック。 CPU時間が長いことは、ユーザーエクスペリエンスが不安定であることを明確に示しています。つまり、ユーザーがアクションと応答の間に顕著な遅延を経験した場合です。 WebPageTestを使用すると、[Chrome]タブで[Capture Dev Tools Timeline]を選択して、WebPageTestを使用する任意のデバイスで実行されるメインスレッドの内訳を表示できます。
    • コンポーネントレベルのCPUコスト
      費やしたCPU時間と同様に、Stoyan Stefanovによって提案されたこのメトリックは、JavaScriptがCPUに与える影響を調査します。 アイデアは、コンポーネントごとのCPU命令数を使用して、全体的なエクスペリエンスへの影響を個別に理解することです。 PuppeteerとChromeを使用して実装できます。
    • FrustrationIndex
      上記の多くのメトリクスは特定のイベントがいつ発生するかを説明していますが、Tim VereeckeのFrustrationIndexは、メトリクスを個別に見るのではなく、メトリクス間のギャップを調べます。 タイトルが表示され、最初のコンテンツが表示され、視覚的に準備ができており、ページが準備ができているなど、エンドユーザーが認識した主要なマイルストーンを確認し、ページの読み込み中のフラストレーションのレベルを示すスコアを計算します。 ギャップが大きいほど、ユーザーがイライラする可能性が高くなります。 ユーザーエクスペリエンスに適したKPIになる可能性があります。 Timは、FrustrationIndexとその仕組みに関する詳細な投稿を公開しています。
    • 広告の重量への影響
      あなたのサイトが広告によって生み出された収入に依存しているなら、広告関連のコードの重みを追跡することは役に立ちます。 Paddy Gantiのスクリプトは2つのURL(1つは通常のURL、もう1つは広告をブロックする)を作成し、WebPageTestを介してビデオ比較の生成を促し、デルタを報告します。
    • 偏差メトリック
      ウィキペディアのエンジニアが指摘しているように、結果にどの程度の分散が存在するかというデータは、機器の信頼性、および偏差とアウトラーにどれだけ注意を払う必要があるかを示します。 大きな変動は、セットアップで必要な調整の指標です。 また、サードパーティのスクリプトが大幅な変動を引き起こしているなどの理由で、特定のページを確実に測定することがより困難であるかどうかを理解するのにも役立ちます。 また、新しいブラウザバージョンが公開されたときのパフォーマンスの向上を理解するために、ブラウザのバージョンを追跡することもお勧めします。
    • カスタムメトリック
      カスタムメトリックは、ビジネスニーズとカスタマーエクスペリエンスによって定義されます。 重要なピクセル、重要なスクリプト、必要なCSS、および関連するアセットを特定し、それらがユーザーに配信されるまでの時間を測定する必要があります。 その場合は、Hero Rendering Timesを監視するか、Performance APIを使用して、ビジネスにとって重要なイベントの特定のタイムスタンプをマークできます。 また、テストの最後に任意のJavaScriptを実行することで、WebPagetestを使用してカスタムメトリックを収集できます。

    First Meaningful Paint (FMP)は、上記の概要には表示されないことに注意してください。 これは、サーバーがデータを出力する速度についての洞察を提供するために使用されていました。 長いFMPは通常、JavaScriptがメインスレッドをブロックしていることを示していますが、バックエンド/サーバーの問題にも関連している可能性があります。 ただし、このメトリックは、約20%のケースで正確ではないように見えるため、最近非推奨になりました。 これは、より信頼性が高く、推論が容易なLCPに効果的に置き換えられました。 Lighthouseではサポートされなくなりました。 安全なページにいることを確認するために、最新のユーザー中心のパフォーマンスメトリックと推奨事項を再確認してください(ありがとう、Patrick Meenan )。

    Steve Soudersは、これらの指標の多くについて詳細に説明しています。 Time-To-Interactiveは、いわゆるラボ環境で自動監査を実行することによって測定されますが、First Input Delayは実際のユーザーエクスペリエンスを表し、実際のユーザーは顕著な遅延を経験していることに注意してください。 一般に、常に両方を測定して追跡することをお勧めします。

    アプリケーションのコンテキストに応じて、推奨されるメトリックは異なる場合があります。たとえば、Netflix TV UIの場合、キー入力の応答性、メモリ使用量、TTIがより重要であり、Wikipediaの場合、最初/最後の視覚的変更とCPU時間の消費メトリックがより重要です。

    :FIDとTTIはどちらも、スクロール動作を考慮していません。 スクロールはメインスレッドから外れているため、独立して発生する可能性があります。そのため、多くのコンテンツ消費サイトでは、これらのメトリックはそれほど重要ではない可能性があります(ありがとう、Patrick! )。

ユーザー中心のパフォーマンスメトリクスは、実際のユーザーエクスペリエンスへのより良い洞察を提供します
ユーザー中心のパフォーマンスメトリックは、実際のユーザーエクスペリエンスに対するより良い洞察を提供します。 First Input Delay(FID)は、まさにそれを達成しようとする新しいメトリックです。 (大プレビュー)
oveviewの新しいコアWebバイタル、LCP <2.5s、FID <100ms、CLS <0.1
oveviewの新しいコアWebバイタル、LCP <2.5s、FID <100ms、CLS <0.1。 (コアWebバイタル、Addy Osmani経由)
  1. Core WebVitalsを測定して最適化します
    長い間、パフォーマンスメトリックは非常に技術的であり、サーバーの応答速度とブラウザの読み込み速度のエンジニアリングビューに焦点を当てていました。 指標は何年にもわたって変化しており、サーバーのタイミングではなく、実際のユーザーエクスペリエンスをキャプチャする方法を見つけようとしています。 2020年5月、GoogleはCore Web Vitalsを発表しました。これは、ユーザーに焦点を当てた新しいパフォーマンス指標のセットであり、それぞれがユーザーエクスペリエンスの異なる側面を表しています。

    それぞれについて、Googleは許容可能な速度目標の範囲を推奨しています。 この評価に合格するには、すべてのページビューの少なくとも75%が適切な範囲を超えている必要があります。 これらの指標はすぐに注目を集め、2021年5月にコアウェブバイタルがGoogle検索のランキングシグナルになり(ページエクスペリエンスランキングアルゴリズムの更新)、多くの企業がパフォーマンススコアに注目しています。

    これらの指標を念頭に置いてエクスペリエンスを最適化するための便利なテクニックとツールとともに、各コアWebバイタルを1つずつ分解してみましょう。 (この記事の一般的なアドバイスに従うことで、Core Web Vitalsのスコアが向上することに注意してください。)

    • 最大のコンテンツフルペイントLCP )<2.5秒。
      ページの読み込みを測定し、ビューポート内に表示される最大の画像またはテキストブロックのレンダリング時間を報告します。 したがって、LCPは、サーバーの応答時間の遅延、CSSのブロック、実行中のJavaScript(ファーストパーティまたはサードパーティ)、Webフォントの読み込み、高価なレンダリングまたはペイント操作、遅延など、重要な情報のレンダリングを延期するすべての影響を受けます。 -ロードされた画像、スケルトン画面、またはクライアント側のレンダリング。

      良い経験のために、LCPはページが最初にロードを開始したときから2.5秒以内に発生するはずです。 つまり、ページの最初に表示される部分をできるだけ早くレンダリングする必要があります。 そのためには、テンプレートごとに調整された重要なCSSが必要になり、 <head>の順序を調整し、重要なアセットをプリフェッチします(後で説明します)。

      LCPスコアが低い主な理由は、通常、画像です。 十分に最適化されたサーバーでホストされ、クライアント側のレンダリングなしですべて静的で、専用の画像CDNからの画像を使用して、Fast 3Gで2.5秒未満でLCPを配信するには、理論上の最大画像サイズが約144KBにすぎないことを意味します。 そのため、レスポンシブ画像が重要であり、重要な画像を早期にプリロードします( preloadを使用)。

      クイックヒント:ページ上でLCPと見なされるものを見つけるには、DevToolsで、パフォーマンスパネルの[タイミング]の下にあるLCPバッジにカーソルを合わせることができます(ありがとう、Tim Kadlec !)。

    • 最初の入力遅延FID )<100ms。
      UIの応答性を測定します。つまり、ブラウザがタップやクリックなどの個別のユーザー入力イベントに反応する前に、他のタスクでビジー状態だった時間を測定します。 これは、特にページのロード中にメインスレッドがビジーであることに起因する遅延をキャプチャするように設計されています。

      目標は、すべてのインタラクションで50〜100ミリ秒以内にとどまることです。 そこに到達するには、長いタスクを特定し(メインスレッドを50ミリ秒以上ブロックする)、それらを分割し、バンドルを複数のチャンクにコード分割し、JavaScriptの実行時間を短縮し、データフェッチを最適化し、サードパーティのスクリプト実行を延期する必要があります、JavaScriptをWebワーカーのバックグラウンドスレッドに移動し、プログレッシブハイドレーションを使用してSPAのリハイドレーションコストを削減します。

      クイックヒント:一般に、より良いFIDスコアを取得するための信頼できる戦略は、大きなバンドルを小さなバンドルに分割し、ユーザーが必要なときに必要なものを提供することでメインスレッドの作業を最小限に抑えることです。これにより、ユーザーの操作が遅れることはありません。 。 これについては、以下で詳しく説明します。

    • 累積レイアウトシフトCLS )<0.1。
      UIの視覚的な安定性を測定して、スムーズで自然な相互作用を保証します。つまり、ページの存続期間中に発生するすべての予期しないレイアウトシフトのすべての個々のレイアウトシフトスコアの合計です。 個々のレイアウトシフトは、すでに表示されている要素がページ上の位置を変更するたびに発生します。 コンテンツのサイズと移動距離に基づいてスコアが付けられます。

      したがって、シフトが表示されるたびに(たとえば、フォールバックフォントとWebフォントのフォントメトリックが異なる場合、広告、埋め込み、iframeが遅れる場合、画像/動画のサイズが予約されていない場合、CSSが遅れて再描画を強制する場合、または変更が挿入される場合)後期JavaScript—CLSスコアに影響を与えます。 優れたエクスペリエンスの推奨値は、CLS <0.1です。

    Core Web Vitalsは、予測可能な年間サイクルで、時間の経過とともに進化することになっていることに注意してください。 初年度のアップデートでは、First ContentfulPaintがCoreWeb Vitalsに昇格し、FIDしきい値が低くなり、シングルページアプリケーションのサポートが向上することを期待している可能性があります。 また、セキュリティ、プライバシー、およびアクセシビリティ(!)の考慮事項とともに、負荷が増加した後のユーザー入力への応答が表示される場合があります。

    Core Web Vitalsに関連して、調べる価値のある有用なリソースや記事がたくさんあります。

    • Web Vitals Leaderboardを使用すると、モバイル、タブレット、デスクトップ、および3Gと4Gでの競合とスコアを比較できます。
    • Core SERP Vitalsは、Google検索結果にCrUXのCore WebVitalsを表示するChrome拡張機能です。
    • シンプルなGIF(コマンドラインからも利用可能)でCLSを視覚化するレイアウトシフトGIFジェネレーター。
    • web-vitalsライブラリは、Core Web Vitalsを収集して、Google Analytics、Google Tag Manager、またはその他の分析エンドポイントに送信できます。
    • WebPageTestを使用したWebVitalsの分析では、PatrickMeenanがWebPageTestがコアWebVitalsに関するデータを公開する方法を調査します。
    • Core Web Vitalsを使用した最適化、Addy Osmaniによる50分のビデオで、eコマースのケーススタディでCore WebVitalsを改善する方法を紹介しています。
    • 実際の累積レイアウトシフトと実世界の累積レイアウトシフトは、Nic Jansmaによる包括的な記事であり、CLSに関するほとんどすべてと、バウンス率、セッション時間、レイジクリックなどの主要な指標との相関関係について説明しています。
    • JavaScriptで要求/呼び出されたときに、プロパティまたはメソッドの概要を含むリフローを強制するもの。これにより、ブラウザーがスタイルとレイアウトを同期的に計算します。
    • CSSトリガーは、どのCSSプロパティがレイアウト、ペイント、コンポジットをトリガーするかを示します。
    • レイアウトの不安定性の修正は、WebPageTestを使用してレイアウトの不安定性の問題を特定して修正するためのウォークスルーです。
    • 累積レイアウトシフト、レイアウト不安定性メトリック、CLSに関するBoris Schapiraによる別の非常に詳細なガイド、計算方法、測定方法、および最適化方法。
    • コアWebバイタルを改善する方法、各メトリック(FCP、TTI、TBTなどの他のWebバイタルを含む)の発生時期と測定方法に関するSimonHearneによる詳細ガイド。

    では、Core Web Vitalsは従うべき究極の指標ですか? 完全ではありません。 それらは、Cloudflare、Treo、SpeedCurve、Calibre、WebPageTest(すでにフィルムストリップビューにあります)、Newrelic、Shopify、Next.js、すべてのGoogleツール(PageSpeed Insights、Lighthouse + CI、Search)を含むほとんどのRUMソリューションとプラットフォームで実際に公開されていますコンソールなど)および他の多く。

    ただし、Katie Sylor-Millerが説明しているように、Core Web Vitalsの主な問題のいくつかは、クロスブラウザーのサポートがないことです。ユーザーエクスペリエンスのライフサイクル全体を実際に測定しているわけではありません。さらに、FIDの変化と相関関係を関連付けることは困難です。ビジネス成果のあるCLS。

    Core Web Vitalsの進化を期待する必要があるため、パフォーマンスの観点から自分の立場をよりよく理解するために、常にWebVitalsをカスタム調整されたメトリックと組み合わせるのが合理的であるように思われます。

  2. オーディエンスを代表するデバイスでデータを収集します。
    正確なデータを収集するには、テストするデバイスを徹底的に選択する必要があります。 ほとんどの企業では、これは分析を調べ、最も一般的なデバイスタイプに基づいてユーザープロファイルを作成することを意味します。 しかし、多くの場合、分析だけでは全体像を把握することはできません。 ターゲットオーディエンスのかなりの部分が、エクスペリエンスが遅すぎるという理由だけでサイトを放棄している(そして戻ってこない)可能性があり、その理由で、デバイスが分析で最も人気のあるデバイスとして表示される可能性は低いです。 したがって、ターゲットグループ内の一般的なデバイスについてさらに調査を行うことをお勧めします。

    IDCによると、2020年には世界的に、出荷されたすべての携帯電話の84.8%がAndroidデバイスです。 平均的な消費者は2年ごとに電話をアップグレードし、米国では電話の交換サイクルは33か月です。 世界中で最も売れている平均的な電話の価格は200ドル未満です。

    したがって、代表的なデバイスは、少なくとも24か月経過し、200ドル以下のコストで、低速の3G、400msのRTT、400kbpsの転送で動作するAndroidデバイスですが、少し悲観的です。 もちろん、これはあなたの会社にとっては非常に異なるかもしれませんが、それはそこにいる大多数の顧客の十分に近い近似です。 実際、ターゲット市場の現在のAmazonベストセラーを調べるのは良い考えかもしれません。 (ポインターをくれたTim Kadlec、Henri Helvetica、Alex Russellに感謝します!

    新しいサイトやアプリを構築するときは、常にターゲット市場の現在のAmazonベストセラーを最初に確認してください
    新しいサイトやアプリを構築するときは、常にターゲット市場の現在のAmazonベストセラーを最初に確認してください。 (大プレビュー)

    その場合、どのテストデバイスを選択しますか? 上で概説したプロファイルによく適合するもの。 少し古いMotoG4 / G5 Plus、ミッドレンジのSamsungデバイス(Galaxy A50、S8)、Nexus 5X、Xiaomi Mi A3、Xiaomi RedmiNoteなどの優れた中道デバイスを選択することをお勧めします7とAlcatel1XやCubotX19のような遅いデバイス、おそらくオープンデバイスラボ。 低速のサーマルスロットルデバイスでテストする場合は、Nexus4を入手することもできます。価格は約100ドルです。

    また、各デバイスで使用されているチップセットを確認し、 1つのチップセットを過剰に表現しないでください。数世代のSnapdragonとApple、およびローエンドのRockchip、Mediatekで十分です(ありがとう、Patrick!)

    手元にデバイスがない場合は、スロットルされたCPU(5倍の速度低下)を使用してスロットルされた3Gネットワ​​ーク(たとえば、300ms RTT、1.6 Mbpsダウン、0.8 Mbpsアップ)でテストすることにより、デスクトップでモバイルエクスペリエンスをエミュレートします。 最終的には、通常の3G、低速4G(たとえば、170ms RTT、9 Mbpsダウン、9Mbpsアップ)、およびWi-Fiに切り替えます。 パフォーマンスへの影響をより明確にするために、火曜日に2Gを導入したり、オフィスにスロットルされた3G / 4Gネットワ​​ークをセットアップしてテストを高速化することもできます。

    モバイルデバイスでは、デスクトップマシンと比較して4倍から5倍の速度低下が予想されることに注意してください。 モバイルデバイスには、さまざまなGPU、CPU、メモリ、およびさまざまなバッテリー特性があります。 そのため、平均的なデバイスのプロファイルを適切に作成し、そのようなデバイスで常にテストすることが重要です。

  3. 最も遅い曜日を紹介します
    最も遅い曜日を紹介します。 Facebookは、遅い接続の可視性と感度を高めるために2G火曜日を導入しました。 (画像ソース)

    幸いなことに、データの収集を自動化し、これらの指標に従ってWebサイトのパフォーマンスを経時的に測定するのに役立つ多くの優れたオプションがあります。 優れたパフォーマンスの全体像は、一連のパフォーマンスメトリック、ラボデータ、およびフィールドデータをカバーしていることに注意してください。

    • 合成テストツールは、事前定義されたデバイスとネットワーク設定( LighthouseCalibreWebPageTestなど)を使用して、再現可能な環境でラボデータを収集します。
    • Real User MonitoringRUM )ツールは、ユーザーの操作を継続的に評価し、フィールドデータを収集します(例: SpeedCurveNew Relic —ツールは総合的なテストも提供します)。

    前者は、製品での作業中にパフォーマンスの問題を特定、切り分け、修正するのに役立つため、開発中に特に役立ちます。 後者は、ユーザーが実際にサイトにアクセスしたときに、ライブで発生しているパフォーマンスのボトルネックを理解するのに役立つため、長期的なメンテナンスに役立ちます。

    ナビゲーションタイミング、リソースタイミング、ペイントタイミング、ロングタスクなどの組み込みのRUM APIを利用することで、合成テストツールとRUMを組み合わせて、アプリケーションのパフォーマンスの全体像を把握できます。 Calibre、Treo、SpeedCurve、mPulse、Boomerang、Sitespeed.ioを使用できます。これらはすべて、パフォーマンス監視に最適なオプションです。 さらに、Server Timingヘッダーを使用すると、バックエンドとフロントエンドのパフォーマンスをすべて1か所で監視することもできます。

    :たとえば、DevToolsは実装方法が原因でHTTP / 2プッシュとのやり取りに問題があるため、ブラウザーの外部でネットワークレベルのスロットルを選択する方が常に安全です(ありがとう、Yoav、Patrick !)。 Mac OSの場合、Network Link Conditioner、Windows Windows Traffic Shaper、Linux netem、およびFreeBSDdummynetを使用できます。

    Lighthouseでテストする可能性が高いため、次のことができることに注意してください。

    • Lighthouse CIを使用して、Lighthouseスコアを経時的に追跡します(非常に印象的です)。
    • GitHub ActionsでLighthouseを実行して、すべてのPRと一緒にLighthouseレポートを取得します。
    • サイトのすべてのページで(Lightouse Paradeを介して)Lighthouseパフォーマンス監査を実行し、出力をCSVとして保存します。
    • 詳細を調べる必要がある場合は、Lighthouse ScoresCalculatorとLighthouseメトリックウェイトを使用してください。
    • LighthouseはFirefoxでも利用できますが、内部ではPageSpeed Insights APIを使用し、ヘッドレスChrome79ユーザーエージェントに基づいてレポートを生成します。
Lighthouse CIは非常に注目に値します。Lighthouseの結果に対して継続的に実行、保存、取得、およびアサートするための一連のツール
Lighthouse CIは非常に注目に値します。Lighthouseの結果に対して継続的に実行、保存、取得、およびアサートするための一連のツールです。 (大プレビュー)
  1. テスト用に「クリーン」プロファイルと「顧客」プロファイルを設定します。
    パッシブモニタリングツールでテストを実行している間は、ウイルス対策とバックグラウンドCPUタスクをオフにし、バックグラウンド帯域幅転送を削除し、ブラウザ拡張機能を使用せずにクリーンなユーザープロファイルでテストして、結果の偏りを回避するのが一般的な戦略です(FirefoxおよびChrome)。
    DebugBearのレポートは、パスワードマネージャー、広告ブロッカー、EvernoteやGrammarlyなどの人気のあるアプリケーションを含む20の最も遅い拡張機能を強調しています
    DebugBearのレポートは、パスワードマネージャー、広告ブロッカー、EvernoteやGrammarlyなどの人気のあるアプリケーションを含む20の最も遅い拡張機能を強調しています。 (大プレビュー)

    ただし、顧客が頻繁に使用するブラウザ拡張機能を調べて、専用の「顧客」プロファイルでテストすることもお勧めします。 実際、一部の拡張機能はアプリケーションのパフォーマンスに大きな影響を与える可能性があり(2020 Chrome拡張機能パフォーマンスレポート)、ユーザーがそれらを頻繁に使用する場合は、事前に説明することをお勧めします。 したがって、「クリーンな」プロファイルの結果だけでは楽観的すぎて、実際のシナリオではつぶれる可能性があります。

  2. パフォーマンスの目標を同僚と共有します。
    今後の誤解を避けるために、パフォーマンスの目標がチームのすべてのメンバーによく知られていることを確認してください。 設計、マーケティング、またはその間のすべての決定にはパフォーマンスへの影響があり、チーム全体に責任と所有権を分散させることで、後でパフォーマンスに焦点を当てた決定を合理化できます。 パフォーマンスバジェットおよび初期に定義された優先順位に対して設計上の決定をマップします。

現実的な目標の設定

  1. 100ミリ秒の応答時間、60fps。
    インタラクションをスムーズに感じるために、インターフェースにはユーザーの入力に応答するための100ミリ秒があります。 それより長くなると、ユーザーはアプリが遅れていると認識します。 ユーザー中心のパフォーマンスモデルであるRAILは、健全なターゲットを提供します。100ミリ秒未満の応答を可能にするには、ページは遅くとも50ミリ秒ごとに制御をメインスレッドに戻す必要があります。 推定入力遅延は、そのしきい値に達しているかどうかを示します。理想的には、50ミリ秒未満である必要があります。 アニメーションのような高圧のポイントについては、できる限り何もしないのが最善であり、できない場合は絶対的な最小値を設定します。

    ユーザー中心のパフォーマンスモデルであるRAIL。
    ユーザー中心のパフォーマンスモデルであるRAIL。

    また、アニメーションの各フレームは16ミリ秒未満で完了する必要があります。これにより、1秒あたり60フレーム(1秒÷60 = 16.6ミリ秒)、できれば10ミリ秒未満で完了します。 ブラウザは新しいフレームを画面にペイントするのに時間がかかるため、16.6ミリ秒のマークに達する前にコードの実行を終了する必要があります。 私たちは120fpsについての会話を始めており(たとえば、iPad Proの画面は120Hzで動作します)、Surmaは120fpsのレンダリングパフォーマンスソリューションをいくつかカバーしていますが、それはおそらくまだ私たちが見ているターゲットではありません

    パフォーマンスの期待については悲観的ですが、インターフェイスデザインについては楽観的であり、アイドル時間を賢く使用してください(idlize、idle-until-urgent、react-idleを確認してください)。 明らかに、これらのターゲットは、ロードパフォーマンスではなく、ランタイムパフォーマンスに適用されます。

  2. FID <100ms、LCP <2.5s、3GでTTI <5​​s、クリティカルファイルサイズバジェット<170KB(gzip圧縮)。
    達成するのは非常に難しいかもしれませんが、最終的な目標は5秒未満のインタラクティブ時間であり、繰り返し訪問する場合は2秒未満を目標とします(サービスワーカーでのみ達成可能)。 2.5秒未満の最大のコンテンツフルペイントを目指し、合計ブロッキング時間累積レイアウトシフトを最小限に抑えます。 許容可能な最初の入力遅延は100ms〜70ms未満です。 上記のように、ベースラインは、400msのRTTと400kbpsの転送速度でエミュレートされた低速の3Gネットワ​​ーク上の200ドルのAndroid携帯電話(Moto G4など)であると考えています。

    Web上でコンテンツを迅速に配信するための合理的な目標を効果的に形作る2つの主要な制約があります。 一方では、TCPスロースタートによるネットワーク配信の制約があります。 HTMLの最初の14KB(10 TCPパケット、各1460バイト、約14.25 KBになりますが、文字通りとは言えません)は、最も重要なペイロードチャンクであり、最初のラウンドトリップで提供できる予算の唯一の部分です(これは、モバイルウェイクアップ時間のために400msRTTで1秒で取得するすべてです)。

    IlyaGrigorikによる高性能ブラウザネットワーキング
    TCP接続では、小さな輻輳ウィンドウから始めて、ラウンドトリップごとに2倍にします。 最初の往復では、14KBを収めることができます。 From:IlyaGrigorikによる高性能ブラウザネットワーキング。 (大プレビュー)

    :TCPは一般にネットワーク接続をかなり活用していないため、GoogleはTCPボトルネック帯域幅とRRT( BBR )、TCP遅延制御TCPフロー制御アルゴリズムを開発しました。最新のWeb用に設計されており、実際の輻輳に対応します。 TCPのようにパケット損失が発生するのではなく、はるかに高速で、スループットが高く、待ち時間が短くなります。また、アルゴリズムの動作も異なります(ありがとう、Victor、Barry! )。

    一方、JavaScriptの解析と実行時間のために、メモリとCPUにハードウェアの制約があります(これらについては後で詳しく説明します)。 最初の段落で述べた目標を達成するには、JavaScriptの重要なファイルサイズの予算を考慮する必要があります。 意見はその予算がどうあるべきかによって異なります(そしてそれはプロジェクトの性質に大きく依存します)が、170KBのJavaScriptをgzipで圧縮した予算は、ミッドレンジの電話で解析およびコンパイルするのに最大1秒かかります。 170KBが解凍時にそのサイズの3倍(0.7MB)に拡張すると仮定すると、それはすでにMoto G4 / G5Plusでの「まともな」ユーザーエクスペリエンスの死の秘訣である可能性があります。

    ウィキペディアのウェブサイトの場合、2020年には、世界中で、コードの実行がウィキペディアのユーザーにとって19%高速になりました。 したがって、前年比のWebパフォーマンスメトリックが安定している場合、環境が改善し続けるにつれて実際に後退しているため、通常は警告サインになります(詳細はGilles Dubucによるブログ投稿にあります)。

    東南アジア、アフリカ、インドなどの成長市場をターゲットにする場合は、非常に異なる一連の制約を調べる必要があります。 Addy Osmaniは、低コストで高品質のデバイスの数が少ない、高品質のネットワークが利用できない、高価なモバイルデータなど、主要なフィーチャーフォンの制約に加えて、これらの環境のPRPL-30予算と開発ガイドラインをカバーしています。

    Addy Osmaniによると、遅延読み込みルートの推奨サイズも35KB未満です。
    Addy Osmaniによると、遅延読み込みルートの推奨サイズも35KB未満です。 (大プレビュー)
    Addy Osmaniは、フィーチャーフォンをターゲットにする場合、PRPL-30のパフォーマンスバジェット(30KB gzip圧縮+最小化された初期バンドル)を提案します
    Addy Osmaniは、フィーチャーフォンをターゲットにする場合、PRPL-30のパフォーマンスバジェット(30KB gzip圧縮+最小化された初期バンドル)を提案しています。 (大プレビュー)

    実際、GoogleのAlex Russellは、妥当な上限として130〜170KBのgzip圧縮を目指すことを推奨しています。 実際のシナリオでは、ほとんどの製品は近くにありません。今日のバンドルサイズの中央値は約452KBで、2015年の初めと比較して53.6%増加しています。中流階級のモバイルデバイスでは、時間の12〜20秒を占めます-To-Interactive

    2019年に世界で最も売れているスマートフォンのGeekbenchCPUパフォーマンスベンチマーク。JavaScriptはシングルコアパフォーマンスを強調し、CPUに依存します
    2019年に世界で最も売れているスマートフォンのGeekbenchCPUパフォーマンスベンチマーク。JavaScriptはシングルコアパフォーマンスを強調し(他のWebプラットフォームよりも本質的にシングルスレッドであることを忘れないでください)、CPUに依存します。 Addyの記事「20ドルのフィーチャーフォンでWebページを高速にロードする」から。 (大プレビュー)

    ただし、バンドルサイズの予算を超えることもできます。 たとえば、ブラウザのメインスレッドのアクティビティ、つまりレンダリングを開始する前のペイント時間に基づいてパフォーマンスバジェットを設定したり、フロントエンドのCPUホッグを追跡したりできます。 Calibre、SpeedCurve、Bundlesizeなどのツールは、予算を抑えるのに役立ち、ビルドプロセスに統合できます。

    最後に、パフォーマンスバジェットはおそらく固定値であってはなりません。 ネットワーク接続に応じて、パフォーマンスバジェットを調整する必要がありますが、低速接続のペイロードは、使用方法に関係なく、はるかに「高価」です。

    :HTTP / 2、今後の5GおよびHTTP / 3、急速に進化する携帯電話、繁栄するSPAの時代に、このような厳格な予算を設定するのは奇妙に聞こえるかもしれません。 ただし、混雑したネットワークからゆっくりと開発されているインフラストラクチャ、データキャップ、プロキシブラウザ、データ保存モード、卑劣なローミング料金など、ネットワークとハードウェアの予測不可能な性質に対処する場合は、合理的に聞こえます。

AddyOsmaniによる「FastByDefault:ModernLoadingBestPractices」から
Fast By Defaultから:Addy Osmaniによる最新の読み込みのベストプラクティス(スライド19)
パフォーマンスバジェットは、平均的なモバイルデバイスのネットワーク条件に応じて調整する必要があります
パフォーマンスバジェットは、平均的なモバイルデバイスのネットワーク条件に応じて調整する必要があります。 (画像ソース:Katie Hempenius)(大プレビュー)

環境の定義

  1. ビルドツールを選択して設定します。
    最近クールだと思われるものにはあまり注意を払わないでください。 Grunt、Gulp、Webpack、Parcel、またはツールの組み合わせなど、構築する環境に固執します。 必要な結果が得られ、ビルドプロセスの維持に問題がない限り、問題なく実行できます。

    ビルドツールの中で、Rollupは勢いを増し続けており、Snowpackも同様ですが、Webpackは最も確立されたツールのようで、ビルドのサイズを最適化するために文字通り何百ものプラグインを利用できます。 Webpackロードマップ2021に注意してください。

    最近登場した最も注目すべき戦略の1つは、重複コードを最小限に抑えるためのNext.jsとGatsbyのWebpackを使用したグラニュラーチャンクです。 デフォルトでは、すべてのエントリポイントで共有されていないモジュールは、それを使用しないルートに対して要求できます。 これは、必要以上に多くのコードがダウンロードされるため、オーバーヘッドになることになります。 Next.jsの詳細なチャンクでは、サーバー側のビルドマニフェストファイルを使用して、出力されたチャンクがさまざまなエントリポイントで使用されているかどうかを判断できます。

    Webpackプロジェクトで重複するコードを減らすために、Next.jsとGatsbyでデフォルトで有効になっているきめ細かいチャンクを使用できます
    Webpackプロジェクトで重複するコードを減らすために、Next.jsとGatsbyでデフォルトで有効になっているきめ細かいチャンクを使用できます。 画像クレジット:Addy Osmani (大プレビュー)

    SplitChunksPluginを使用すると、複数のルート間で重複したコードをフェッチしないように、いくつかの条件に応じて複数の分割チャンクが作成されます。 これにより、ナビゲーション中のページの読み込み時間とキャッシュが改善されます。 Next.js9.2およびGatsbyv2.20.7で出荷されます。

    ただし、Webpackの使用を開始するのは難しい場合があります。 したがって、Webpackに飛び込みたい場合は、いくつかの優れたリソースがあります。

    • Webpackのドキュメント—明らかに—は良い出発点であり、Webpack — RajaRaoによる紛らわしいビットとAndrewWelchによる注釈付きWebpackConfigも同様です。
    • Sean LarkinはWebpackに関する無料のコースを持っています:CoreConceptsとJeffreyWayは、Webpackに関する素晴らしい無料のコースをすべての人にリリースしました。 どちらもWebpackに飛び込むための素晴らしい入門書です。
    • Webpack Fundamentalsは、FrontendMastersからリリースされたSeanLarkinによる非常に包括的な4時間コースです。
    • Webpackの例には、トピックと目的によって分類された、すぐに使用できる何百ものWebpack構成があります。 ボーナス:基本的な構成ファイルを生成するWebpack構成コンフィギュレーターもあります。
    • awesome-webpackは、Angular、React、フレームワークに依存しないプロジェクトの記事、ビデオ、コース、書籍、例など、便利なWebpackリソース、ライブラリ、ツールの厳選されたリストです。
    • Webpackを使用した本番アセットビルドの高速化への道のりは、チームがRequireJSベースのJavaScriptビルドシステムの使用からWebpackの使用に切り替えた方法と、ビルドを最適化し、平均4分で13,200を超えるアセットを管理する方法に関するEtsyのケーススタディです。
    • Webpackのパフォーマンスのヒントは、Ivan Akulovによる金鉱のスレッドであり、特にWebpackに焦点を当てたものを含め、パフォーマンスに焦点を当てた多くのヒントを備えています。
    • awesome-webpack-perfは、パフォーマンスのための便利なWebpackツールとプラグインを備えた金鉱のGitHubリポジトリです。 IvanAkulovによっても維持されています。
Webpackを使用した高速プロダクションビルドへのEtsyの旅の視覚化
Webpackを使用した高速プロダクションビルドへのEtsyの旅(Addy Osmani経由)(大プレビュー)
  1. デフォルトとしてプログレッシブエンハンスメントを使用します。
    それでも、これらすべての年月を経て、フロントエンドのアーキテクチャと展開の指針としてプログレッシブエンハンスメントを維持することは安全な策です。 最初にコアエクスペリエンスを設計および構築してから、対応するブラウザーの高度な機能でエクスペリエンスを強化し、復元力のあるエクスペリエンスを作成します。 あなたのウェブサイトが最適ではないネットワーク上の貧弱なブラウザで貧弱な画面を備えた遅いマシンで高速に実行される場合、それはまともなネットワーク上の優れたブラウザを備えた高速マシンでのみ高速に実行されます。

    実際、アダプティブモジュールサービングでは、プログレッシブエンハンスメントを別のレベルに引き上げ、ローエンドデバイスに「ライト」コアエクスペリエンスを提供し、ハイエンドデバイス向けのより高度な機能でエンハンスメントしているようです。 プログレッシブエンハンスメントがすぐに消えていく可能性はほとんどありません。

  2. 強力なパフォーマンスベースラインを選択します。
    ネットワーク、サーマルスロットリング、キャッシュエビクション、サードパーティスクリプト、パーサーブロッキングパターン、ディスクI / O、IPCレイテンシ、インストールされた拡張機能、ウイルス対策ソフトウェアとファイアウォール、バックグラウンドCPUタスク、ハードウェアとメモリの制約など、読み込みに影響を与える未知数が非常に多いL2 / L3キャッシング、RTTSの違い— JavaScriptは、デフォルトでレンダリングをブロックするWebフォントと、多くの場合メモリを消費しすぎる画像の次に、エクスペリエンスのコストが最も高くなります。 パフォーマンスのボトルネックがサーバーからクライアントに移行するにつれ、開発者として、これらの未知のすべてをより詳細に検討する必要があります。

    クリティカルパスHTML / CSS / JavaScript、ルーター、状態管理、ユーティリティ、フレームワーク、およびアプリケーションロジックがすでに含まれている170KBの予算では、ネットワーク転送コスト、解析/コンパイル時間、およびランタイムコストを徹底的に調査する必要があります私たちの選択のフレームワークの。 幸いなことに、ここ数年で、ブラウザがスクリプトを解析およびコンパイルする速度が大幅に向上しました。 それでも、JavaScriptの実行は依然として主要なボトルネックであるため、スクリプトの実行時間とネットワークに細心の注意を払うことは影響を与える可能性があります。

    Tim Kadlecは、最新のフレームワークのパフォーマンスについて素晴らしい調査を実施し、「JavaScriptフレームワークにはコストがかかる」という記事にまとめました。 スタンドアロンフレームワークの影響についてよく話しますが、Timが指摘しているように、実際には、複数のフレームワークを使用することも珍しくありません。 おそらく、古いバージョンのAngularを使用するいくつかのレガシーアプリケーションとともに、最新のフレームワークにゆっくりと移行されている古いバージョンのjQueryです。 したがって、ハイエンドデバイスでも、ユーザーエクスペリエンスをほとんど使用できないようにする、JavaScriptバイトとCPU実行時間の累積コストを調査する方が合理的です。

    一般に、最新のフレームワークはそれほど強力でないデバイスを優先していないため、電話とデスクトップでのエクスペリエンスは、パフォーマンスの点で劇的に異なることがよくあります。 調査によると、ReactまたはAngularを使用しているサイトは、他のサイトよりもCPUに多くの時間を費やしています(もちろん、ReactがVue.jsよりもCPUで高価であるとは限りません)。

    ティムによれば、明らかなことが1つあります。「フレームワークを使用してサイトを構築している場合、最良のシナリオであっても、初期パフォーマンスの点でトレードオフが発生します。」

フレームワークのコスト、JavaScriptのCPU時間:SPAサイトのパフォーマンスが低い
フレームワークのコスト、JavaScriptバイ:SPAサイトは(まだ)パフォーマンスが悪い
モバイルデバイスのスクリプト関連のCPU時間とdesktopvデバイスのJavaScriptバイト。 一般に、ReactまたはAngularを使用するサイトは、他のサイトよりもCPUに多くの時間を費やします。 ただし、サイトの構築方法によって異なります。 ティム・カドレックによる調査。 (大プレビュー)
  1. フレームワークと依存関係を評価します。
    現在、すべてのプロジェクトにフレームワークが必要なわけではなく、シングルページアプリケーションのすべてのページにフレームワークをロードする必要があるわけでもありません。 Netflixの場合、「React、いくつかのライブラリ、および対応するアプリコードをクライアント側から削除すると、JavaScriptの総量が200 KB以上削減され、ログアウトしたホームページのNetflixの双方向性が50%以上短縮されました。 。」 次に、チームは、ユーザーがランディングページで費やした時間を利用して、ユーザーがランディングする可能性が高い後続のページのReactをプリフェッチしました(詳細については、以下をお読みください)。

    では、重要なページの既存のフレームワークを完全に削除するとどうなるでしょうか。 Gatsbyを使用すると、静的HTMLファイルからGatsbyによって作成されたすべてのJavaScriptファイルを削除するgatsby-plugin-no-javascriptを確認できます。 Vercelでは、特定のページの本番環境でランタイムJavaScriptを無効にすることもできます(実験的)。

    フレームワークが選択されると、少なくとも数年間はそのフレームワークを使用し続けるため、フレームワークを使用する必要がある場合は、選択内容が十分に考慮されていることを確認する必要があります。これは、特に主要なパフォーマンス指標に当てはまります。気に。

    データによると、デフォルトでは、フレームワークは非常に高価です。Reactページの58.6%が1 MBを超えるJavaScriptを出荷し、Vue.jsページの読み込みの36%が1.5秒未満のFirst ContentfulPaintを持っています。 Ankur Sethiの調査によると、「Reactアプリケーションは、最適化しても、インドの平均的な電話で約1.1秒より速く読み込まれることはありません。Angularアプリの起動には常に少なくとも2.7秒かかります。 Vueアプリのユーザーは、使用を開始する前に少なくとも1秒待つ必要があります。」 とにかくプライマリーマーケットとしてインドをターゲットにしていないかもしれませんが、最適ではないネットワーク条件でサイトにアクセスするユーザーは、同等のエクスペリエンスを得ることができます。

    もちろん、SPAを高速化すること可能ですが、すぐに使用できる高速ではないため、SPAを高速化して維持するために必要な時間と労力を考慮する必要があります。 早い段階で軽量のベースラインパフォーマンスコストを選択することで、おそらく簡単になるでしょう。

    では、どのようにフレームワークを選択するのでしょうか? オプションを選択する前に、少なくともサイズの合計コスト+初期実行時間を考慮することをお勧めします。 Preact、Inferno、Vue、Svelte、Alpine、Polymerなどの軽量オプションを使用すると、問題なく作業を行うことができます。 ベースラインのサイズは、アプリケーションのコードの制約を定義します。

    Seb Markbageが指摘しているように、フレームワークの起動コストを測定する良い方法は、最初にビューをレンダリングし、次にそれを削除してから、フレームワークがどのようにスケーリングするかを示すことができるので、もう一度レンダリングすることです。 最初のレンダリングは、レイジーにコンパイルされたコードの束をウォームアップする傾向があります。これは、より大きなツリーがスケーリングするときに恩恵を受けることができます。 2番目のレンダリングは、基本的に、ページが複雑になるにつれて、ページでのコードの再利用がパフォーマンス特性にどのように影響するかをエミュレーションしたものです。

    機能、アクセシビリティ、安定性、パフォーマンス、パッケージエコシステム、コミュニティ、学習曲線、ドキュメント、ツール、実績を調査することで、Sacha Greifの12ポイントスケールスコアリングシステムで候補者(または一般的なJavaScriptライブラリ)を評価することができます。 、チーム、互換性、セキュリティなど。

    Perf Trackは、フレームワークのパフォーマンスを大規模に追跡します
    Perf Trackは、フレームワークのパフォーマンスを大規模に追跡します。 (大プレビュー)

    また、長期間にわたってWeb上で収集されたデータに依存することもできます。 たとえば、Perf Trackはフレームワークのパフォーマンスを大規模に追跡し、Angular、React、Vue、Polymer、Preact、Ember、Svelte、およびAMPで構築されたWebサイトのオリジン集約コアWebバイタルスコアを示します。 Gatsby、Next.js、またはCreate React Appで構築されたWebサイト、およびNuxt.js(Vue)またはSapper(Svelte)で構築されたWebサイトを指定して比較することもできます。

    良い出発点は、アプリケーションに適したデフォルトのスタックを選択することです。 Gatsby(React)、Next.js(React)、Vuepress(Vue)、Preact CLI、およびPWA Starter Kitは、平均的なモバイルハードウェアで箱から出してすぐにロードするための妥当なデフォルトを提供します。 また、ReactとAngularのweb.devフレームワーク固有のパフォーマンスガイダンスもご覧ください(ありがとう、Phillip! )。

    そして、おそらく、シングルページアプリケーションを構築するためにもう少し新鮮なアプローチを取ることができます— Turbolinks、JSONの代わりにHTMLを使用してビューをレンダリングする15KBのJavaScriptライブラリ。 したがって、リンクをたどると、Turbolinksは自動的にページをフェッチし、その<body>をスワップインし、その<head>をマージします。すべて、ページ全体の読み込みのコストは発生しません。 スタック(Hotwire)に関する簡単な詳細と完全なドキュメントを確認できます。

売れ筋の携帯電話の計算パフォーマンスを示すヒストグラムのようなグラフ
売れ筋の携帯電話のCPUとコンピューティングパフォーマンス(画像クレジット:Addy Osmani)(大プレビュー)
  1. クライアント側のレンダリングまたはサーバー側のレンダリング? 両方!
    それは非常に熱心な会話です。 究極のアプローチは、ある種のプログレッシブブートを設定することです。サーバー側のレンダリングを使用して、First Contenful Paintをすばやく取得しますが、インタラクティブまでの時間をFirst Contentful Paintに近づけるために、必要最小限のJavaScriptも含めます。 FCPの後にJavaScriptが遅すぎる場合、ブラウザーは、検出が遅れたJavaScriptの解析、コンパイル、および実行中にメインスレッドをロックし、サイトまたはアプリケーションの対話性を手に負えなくなります。

    これを回避するには、関数の実行を常に個別の非同期タスクに分割し、可能な場合はrequestIdleCallbackを使用します。 WebPackの動的import()サポートを使用してUIの遅延読み込み部分を検討し、ユーザーが本当に必要とするまで読み込み、解析、およびコンパイルのコストを回避します( Addyに感謝します)。

    上記のように、Time to Interactive(TTI)は、ナビゲーションと対話性の間の時間を示します。 詳細には、最初のコンテンツがレンダリングされた後の最初の5秒のウィンドウを確認することでメトリックが定義されます。このウィンドウでは、JavaScriptタスクに50ミリ秒以上かかることはありません( Long Tasks )。 50ミリ秒を超えるタスクが発生した場合、5秒のウィンドウの検索が最初からやり直されます。 その結果、ブラウザは最初にInteractiveに到達したと見なし、 Frozenに切り替えるだけで、最終的にInteractiveに戻ります。

    Interactiveに到達すると、オンデマンドまたは時間の許す限り、アプリの重要でない部分を起動できます。 残念ながら、Paul Lewisが気付いたように、フレームワークには通常、開発者に提示できる優先順位の単純な概念がないため、ほとんどのライブラリとフレームワークでプログレッシブブートを実装するのは簡単ではありません。

    それでも、私たちはそこに到達しています。 最近、私たちが探求できる選択肢がいくつかあります。HousseinDjirdehとJason Millerは、Webでのレンダリングに関する講演と、JasonとAddyによる最新のフロントエンドアーキテクチャに関する記事で、これらのオプションの優れた概要を示しています。 以下の概要は、彼らの優れた業績に基づいています。

    • フルサーバーサイドレンダリング(SSR)
      WordPressなどの従来のSSRでは、すべてのリクエストはサーバー上で完全に処理されます。 要求されたコンテンツは完成したHTMLページとして返され、ブラウザはすぐにそれをレンダリングできます。 したがって、たとえば、SSRアプリは実際にはDOMAPIを利用できません。 First ContentfulPaintとTimeto Interactiveの間のギャップは通常小さく、HTMLがブラウザにストリーミングされているときにページをすぐにレンダリングできます。

      これにより、ブラウザが応答を受け取る前に処理されるため、クライアントでのデータのフェッチとテンプレート作成のための追加のラウンドトリップが回避されます。 ただし、サーバーの思考時間が長くなり、その結果、最初のバイトまでの時間が長くなり、最新のアプリケーションの応答性の高い豊富な機能を利用できなくなります。

    • 静的レンダリング
      製品をシングルページアプリケーションとしてビルドしますが、すべてのページは、ビルドステップとして最小限のJavaScriptを使用して静的HTMLに事前レンダリングされます。 つまり、静的レンダリングでは、可能なURLごとに個別のHTMLファイルを事前に作成します。これは、多くのアプリケーションでは実現できないものです。 ただし、ページのHTMLをその場で生成する必要がないため、一貫して高速な最初のバイトまでの時間を実現できます。 したがって、ランディングページをすばやく表示してから、後続のページのSPAフレームワークをプリフェッチできます。 Netflixはこのアプローチを採用しており、読み込みと対話までの時間を50%削減しています。

    • (再)ハイドレーションを使用したサーバー側レンダリング(ユニバーサルレンダリング、SSR + CSR)
      SSRとCSRの両方の長所を活用することができます。 水分補給が混ざり合っているため、サーバーから返されるHTMLページには、本格的なクライアント側アプリケーションをロードするスクリプトも含まれています。 理想的には、高速のFirst Contentful Paint(SSRなど)を実現してから、(再)ハイドレーションでレンダリングを続行します。 残念ながら、そうなることはめったにありません。 多くの場合、ページは準備ができているように見えますが、ユーザーの入力に応答できず、怒りのクリックや放棄が発生します。

      Reactを使用すると、ExpressなどのノードサーバーでReactDOMServerモジュールを使用してから、 renderToStringメソッドを呼び出して、最上位のコンポーネントを静的なHTML文字列としてレンダリングできます。

      Vue.jsでは、vue-server-rendererを使用して、 renderToStringを使用してVueインスタンスをHTMLにレンダリングできます。 Angularでは、 @nguniversalを使用して、クライアントリクエストを完全にサーバーでレンダリングされたHTMLページに変換できます。 Next.js(React)またはNuxt.js(Vue)を使用すると、サーバーで完全にレンダリングされたエクスペリエンスをすぐに実現することもできます。

      このアプローチには欠点があります。 その結果、より高速なサーバー側レンダリングを提供しながら、クライアント側アプリの完全な柔軟性を得ることができますが、First ContentfulPaintとTimeTo Interactiveの間のギャップが長くなり、First InputDelayが増加します。 水分補給は非常に費用がかかります。通常、この戦略だけでは、インタラクティブ時間の大幅な遅延が発生するため、十分ではありません。

    • プログレッシブハイドレーション(SSR + CSR)を使用したスト​​リーミングサーバーサイドレンダリング
      Time ToInteractiveとFirstContentful Paintの間のギャップを最小限に抑えるために、一度に複数のリクエストをレンダリングし、コンテンツが生成されるときにコンテンツをチャンクで送信します。 したがって、コンテンツをブラウザに送信する前にHTMLの完全な文字列を待つ必要がないため、最初のバイトまでの時間が短縮されます。

      Reactでは、renderToString()の代わりに、 renderToString()を使用して応答をパイプ処理し、HTMLをチャンクで送信できます。 Vueでは、パイプとストリーミングが可能なrenderToStream()を使用できます。 React Suspenseを使用すると、その目的で非同期レンダリングを使用することもできます。

      クライアント側では、アプリケーション全体を一度に起動するのではなく、コンポーネントを段階的に起動します。 アプリケーションのセクションは、最初にコード分割を使用してスタンドアロンスクリプトに分割され、次に徐々に(優先順位に従って)ハイドレイトされます。 実際、重要なコンポーネントを最初に水和し、残りを後で水和することができます。 クライアント側とサーバー側のレンダリングの役割は、コンポーネントごとに異なる方法で定義できます。 次に、一部のコンポーネントが表示されるまで、またはユーザーインタラクションに必要になるまで、またはブラウザがアイドル状態になるまで、一部のコンポーネントのハイドレーションを延期することもできます。

      Vueの場合、Markus Oberlehnerは、ユーザーインタラクションのハイドレーションと、可視性または特定のユーザーインタラクションのコンポーネントハイドレーションを可能にする初期段階のプラグインであるvue-lazy-hydrationを使用して、SSRアプリのインタラクティブ時間の短縮に関するガイドを公開しました。 Angularチームは、IvyUniversalを使用してプログレッシブハイドレーションに取り組んでいます。 PreactとNext.jsを使用して部分的なハイドレーションを実装することもできます。

    • トリソモルフィックレンダリング
      サービスワーカーを配置すると、初期/非JSナビゲーションにストリーミングサーバーレンダリングを使用し、インストール後にサービスワーカーにナビゲーション用のHTMLのレンダリングを実行させることができます。 その場合、Service Workerはコンテンツを事前レンダリングし、同じセッションで新しいビューをレンダリングするためのSPAスタイルのナビゲーションを有効にします。 サーバー、クライアントページ、およびServiceWorker間で同じテンプレートコードとルーティングコードを共有できる場合にうまく機能します。

    DOMレンダリング、サービスワーカーの事前レンダリング、サーバー側のレンダリングなど、3か所でトリソモーフィックレンダリングがどのように機能するかを示す図
    サーバー、DOM、またはServiceWorkerの3か所で同じコードレンダリングを使用するTrisomorphicレンダリング。 (画像ソース:Google Developers)(大プレビュー)
    • 事前レンダリングによるCSR
      事前レンダリングはサーバー側のレンダリングに似ていますが、サーバー上のページを動的にレンダリングするのではなく、ビルド時にアプリケーションを静的HTMLにレンダリングします。 静的ページはクライアント側のJavaScriptがあまりなくても完全にインタラクティブですが、事前レンダリングの動作は異なります。 基本的に、ビルド時にクライアント側アプリケーションの初期状態を静的HTMLとしてキャプチャしますが、ページをインタラクティブにするには、事前レンダリングを使用してアプリケーションをクライアントで起動する必要があります。

      Next.jsを使用すると、アプリを静的HTMLに事前レンダリングすることで、静的HTMLエクスポートを使用できます。 Gatsbyでは、Reactを使用するオープンソースの静的サイトジェネレーターは、ビルド中にrenderToStaticMarkupメソッドの代わりにrenderToStringメソッドを使用し、メインのJSチャンクがプリロードされ、将来のルートがプリフェッチされます。単純な静的ページには必要のないDOM属性はありません。

      Vueの場合、Vuepressを使用して同じ目標を達成できます。 Webpackでprerender-loaderを使用することもできます。 Naviは静的レンダリングも提供します。

      その結果、最初のバイトまでの時間と最初の満足のいくペイントが改善され、インタラクティブな時間と最初の満足のいくペイントの間のギャップが減少します。 コンテンツが大幅に変更されることが予想される場合、このアプローチを使用することはできません。 さらに、すべてのページを生成するには、すべてのURLを事前に知っておく必要があります。 そのため、一部のコンポーネントは事前レンダリングを使用してレンダリングされる場合がありますが、動的なものが必要な場合は、アプリに依存してコンテンツをフェッチする必要があります。

    • フルクライアントサイドレンダリング(CSR)
      すべてのロジック、レンダリング、および起動はクライアントで実行されます。 その結果、通常、Time ToInteractiveとFirstContentfulPaintの間に大きなギャップが生じます。 その結果、何かをレンダリングするにはアプリ全体をクライアントで起動する必要があるため、アプリケーションの動作が遅くなることがよくあります。

      JavaScriptにはパフォーマンスコストがかかるため、アプリケーションとともにJavaScriptの量が増えるにつれて、JavaScriptの積極的なコード分割と延期は、JavaScriptの影響を抑えるために絶対に必要になります。 このような場合、対話性があまり必要ない場合は、通常、サーバー側のレンダリングの方が適しています。 オプションでない場合は、App ShellModelの使用を検討してください。

      一般的に、SSRはCSRよりも高速です。 それでもなお、これは多くのアプリで非常に頻繁に実装されています。

    では、クライアント側ですか、それともサーバー側ですか? 一般に、完全にクライアント側のフレームワークの使用を、それらを絶対に必要とするページに制限することをお勧めします。 高度なアプリケーションの場合、サーバー側のレンダリングだけに依存することもお勧めできません。 サーバーレンダリングとクライアントレンダリングはどちらも、うまく行かないと大惨事になります。

    CSRまたはSSRのどちらに傾倒している場合でも、重要なピクセルをできるだけ早くレンダリングし、そのレンダリングとインタラクティブ時間のギャップを最小限に抑えるようにしてください。 ページがあまり変更されない場合は事前レンダリングを検討し、可能であればフレームワークの起動を延期します。 サーバー側のレンダリングを使用してHTMLをチャンクでストリーミングし、クライアント側のレンダリングにプログレッシブハイドレーションを実装します。また、可視性、対話、またはアイドル時間中にハイドレイトして、両方の世界を最大限に活用します。

クライアント側とサーバー側のレンダリングのオプションを比較した表
クライアント側とサーバー側のレンダリングのオプションの範囲。 また、アプリケーションアーキテクチャのパフォーマンスへの影響に関するGoogle I / OでのJasonとHousseinの講演も確認してください。 (画像ソース:Jason Miller)(大プレビュー)
左側にプログレッシブハイドレーションなし、右側にプログレッシブハイドレーションがあるAirBnBのウェブサイトの例
AirBnBは漸進的な水分補給を実験してきました。 それらは、不要なコンポーネントを延期し、ユーザーの操作(スクロール)またはアイドル時間中に負荷をかけ、テストにより、TTIを改善できることが示されています。 (大プレビュー)
  1. 静的にいくらサービスを提供できますか?
    大規模なアプリケーションで作業している場合でも、小規模なサイトで作業している場合でも、オンザフライで動的に生成するのではなく、CDN(つまり、JAMスタック)から静的に提供できるコンテンツを検討する価値があります。 パーソナライズオプションが豊富な数千の製品と数百のフィルターがある場合でも、重要なランディングページを静的に提供し、これらのページを選択したフレームワークから切り離したい場合があります。

    静的サイトジェネレーターはたくさんあり、それらが生成するページは非常に高速であることがよくあります。 リクエスト時にサーバーまたはクライアントでページビューを生成する代わりに、事前に構築できるコンテンツが多いほど、パフォーマンスが向上します。

    Markus Oberlehnerは、部分的にハイドレイトされたプログレッシブエンハンスドの静的Webサイトを構築する際に、プログレッシブエンハンスメントと最小のJavaScriptバンドルサイズを実現しながら、静的サイトジェネレーターとSPAを使用してWebサイトを構築する方法を示します。 Markusは、ツールとしてEleventyとPreactを使用し、ツールのセットアップ、部分的なハイドレーション、レイジーハイドレーション、クライアントエントリファイルの追加、Preact用のBabelの構成、およびPreactとRollupのバンドルを最初から最後まで行う方法を示しています。

    最近、大規模なサイトでJAMStackが使用されているため、パフォーマンスに関する新しい考慮事項が登場しました。それはビルド時間です。 実際、新しいデプロイごとに数千ページを構築するのに数分かかる可能性があるため、WordPress、Contentful、Drupal、Netlify CMSなどの一般的なCMSソリューションに統合することで、ビルド時間を60倍改善するGatsbyのインクリメンタルビルドを見ることができます。その他。

    左上にユーザー1、左下にユーザー2を示すフローチャートは、増分ステータス再生成のプロセスを示しています
    Next.jsを使用したインクリメンタル静的再生。 (画像クレジット:Prisma.io)(大プレビュー)

    また、Next.jsは、事前の増分静的生成を発表しました。これにより、実行時に新しい静的ページを追加し、トラフィックが到着したときにバックグラウンドで再レンダリングすることにより、既存のページが既に構築された後に更新できます。 。

    さらに軽量なアプローチが必要ですか? Eleventy、Alpine、Tailwindに関する講演で、軽量のJamstackに向けて、Nicola Goutayは、CSR、SSR、およびその間のすべての違いを説明し、より軽量なアプローチを使用する方法を示し、アプローチを示すGitHubリポジトリを示します。実際には。

  2. PRPLパターンとアプリシェルアーキテクチャの使用を検討してください。
    フレームワークが異なれば、パフォーマンスへの影響も異なり、最適化の戦略も異なるため、依存するフレームワークの要点をすべて明確に理解する必要があります。 Webアプリを構築するときは、PRPLパターンとアプリケーションシェルアーキテクチャを調べてください。 アイデアは非常に単純です。最初のルートをインタラクティブにしてすばやくレンダリングするために必要な最小限のコードをプッシュし、Service Workerを使用してリソースをキャッシュおよび事前キャッシュし、必要なルートを非同期で遅延ロードします。
アプリケーションシェルアーキテクチャのPRPLパターン
PRPLは、重要なリソースのプッシュ、初期ルートのレンダリング、残りのルートの事前キャッシュ、および残りのルートのオンデマンドでの遅延読み込みの略です。
アプリケーションシェルアーキテクチャ
アプリケーションシェルは、ユーザーインターフェイスを強化する最小限のHTML、CSS、およびJavaScriptです。
  1. APIのパフォーマンスを最適化しましたか?
    APIは、エンドポイントを介して内部およびサードパーティのアプリケーションにデータを公開するためのアプリケーションの通信チャネルです。 APIを設計および構築する場合、サーバーとサードパーティのリクエスト間の通信を可能にするための適切なプロトコルが必要です。 Representational State Transfer( REST )は、確立された論理的な選択です。これは、パフォーマンスが高く、信頼性が高く、スケーラブルな方法でコンテンツにアクセスできるようにするために開発者が従う一連の制約を定義します。 REST制約に準拠するWebサービスは、 RESTfulWebサービスと呼ばれます。

    古き良きHTTPリクエストと同様に、APIからデータを取得すると、サーバーの応答の遅延がエンドユーザーに伝播するため、レンダリングが遅延します。 リソースがAPIからデータを取得する場合、対応するエンドポイントからデータを要求する必要があります。 コメント付きの記事や各コメントに著者の写真など、複数のリソースからデータをレンダリングするコンポーネントでは、レンダリングする前にすべてのデータをフェッチするために、サーバーへのラウンドトリップが数回必要になる場合があります。 さらに、RESTを介して返されるデータの量は、多くの場合、そのコンポーネントをレンダリングするために必要な量よりも多くなります。

    多くのリソースがAPIからのデータを必要とする場合、APIがパフォーマンスのボトルネックになる可能性があります。 GraphQLは、これらの問題に対するパフォーマンスの高いソリューションを提供します。 それ自体、GraphQLはAPIのクエリ言語であり、データ用に定義した型システムを使用してクエリを実行するためのサーバー側ランタイムです。 RESTとは異なり、GraphQLは単一のリクエストですべてのデータを取得でき、応答は、RESTで通常発生するようなデータのオーバーまたはアンダーフェッチなしで、まさに必要なものになります。

    さらに、GraphQLはスキーマ(データの構造を示すメタデータ)を使用しているため、データを優先構造に整理できます。たとえば、GraphQLを使用すると、状態管理の処理に使用されるJavaScriptコードを削除して、クライアント上でより高速に実行される、よりクリーンなアプリケーションコード。

    GraphQLの使用を開始したい場合、またはパフォーマンスの問題が発生した場合は、次の記事が非常に役立つ場合があります。

    • GraphQL入門書:EricBaerによる新しい種類のAPIが必要な理由
    • GraphQL入門書:EricBaerによるAPI設計の進化
    • LeonardoLosovizによる最適なパフォーマンスのためのGraphQLサーバーの設計
    • WojciechTrockiによって説明されたGraphQLのパフォーマンス。
Redux / REST(左)とApollo / GraphQL(右)を使用した場合のメッセージのモバイルインターフェイスの2つの例
RESTとGraphQLの違い。左側がRedux + REST、右側がApollo + GraphQLの会話で示されています。 (画像ソース:ハッカー正午)(大プレビュー)
  1. AMPまたはインスタント記事を使用しますか?
    組織の優先順位と戦略に応じて、GoogleのAMP、FacebookのInstant Articles、またはAppleのAppleNewsの使用を検討することをお勧めします。 それらがなくても優れたパフォーマンスを達成できますが、AMP無料のコンテンツ配信ネットワーク(CDN)を備えた堅実なパフォーマンスフレームワークを提供し、InstantArticlesはFacebookでの可視性とパフォーマンスを向上させます。

    ユーザーにとってこれらのテクノロジーの明らかな利点は保証されたパフォーマンスであるため、「通常の」ページや肥大化する可能性のあるページよりも、AMP- / Apple News / InstantPages-リンクを好む場合もあります。 多くのサードパーティコンテンツを処理するコンテンツの多いWebサイトの場合、これらのオプションはレンダリング時間を大幅に短縮するのに役立つ可能性があります。

    そうでない限り。 たとえば、Tim Kadlec氏によると、「AMPドキュメントは対応するドキュメントよりも高速である傾向がありますが、必ずしもページのパフォーマンスが高いとは限りません。AMPは、パフォーマンスの観点から最大の違いを生むものではありません。」

    ウェブサイトの所有者にとってのメリットは明らかです。それぞれのプラットフォームでこれらのフォーマットを発見できることと、検索エンジンでの可視性が向上することです。

    まあ、少なくともそれは以前のようでした。 AMPはTopStoriesの要件ではなくなったため、サイト運営者はAMPから従来のスタックに移行する可能性があります(ありがとう、Barry! )。

    それでも、AMPをPWAのデータソースとして再利用することで、プログレッシブWebAMPを構築することもできます。 欠点? 明らかに、壁に囲まれた庭に存在することで、開発者はコンテンツの別のバージョンを作成および維持できるようになります。インスタント記事やApple Newsの場合、実際のURLはありません(Addy、Jeremyに感謝します)

  2. CDNを賢く選択してください。
    上記のように、動的データの量によっては、コンテンツの一部を静的サイトジェネレーターに「アウトソーシング」し、CDNにプッシュして静的バージョンを提供できるため、サーバ。 実際、これらのジェネレーターのいくつかは、実際にはWebサイトのコンパイラーであり、多くの自動化された最適化がすぐに提供されます。 コンパイラーが時間の経過とともに最適化を追加すると、コンパイルされた出力は時間の経過とともに小さくなり、高速になります。

    CDNは動的コンテンツも提供(およびオフロード)できることに注意してください。 したがって、CDNを静的アセットに制限する必要はありません。 CDNが圧縮と変換(エッジでの画像の最適化とサイズ変更など)を実行するかどうか、サーバーワーカー、A / Bテスト、およびページの静的部分と動的部分を組み立てるエッジ側のインクルードをサポートするかどうかを再確認しますCDNのエッジ(つまり、ユーザーに最も近いサーバー)、およびその他のタスク。 また、CDNがHTTP over QUIC(HTTP / 3)をサポートしているかどうかを確認してください。

    Katie Hempeniusは、CDNのすばらしいガイドを作成しました。このガイドでは、優れたCDNの選択方法、微調整方法、およびCDNを評価する際に留意すべきすべての小さな事項についての洞察を提供しています。 一般に、コンテンツをできるだけ積極的にキャッシュし、Brotli、TLS 1.3、HTTP / 2、HTTP / 3などのCDNパフォーマンス機能を有効にすることをお勧めします。

    :PatrickMeenanとAndyDaviesの調査に基づくと、HTTP / 2の優先順位付けは多くのCDNで効果的に破られているため、CDNを選択する際は注意が必要です。 Patrickは、HTTP / 2の優先順位付けに関する講演で詳細を説明しています(ありがとう、Barry! )。

    CDN名のCDNPerfプレビューとミリ秒単位のクエリ速度
    CDNPerfは、毎日3億のテストを収集して分析することにより、CDNのクエリ速度を測定します。 (大プレビュー)

    CDNを選択するときは、これらの比較サイトを使用して、それらの機能の詳細な概要を確認できます。

    • CDN比較、Cloudfront、Aazure、KeyCDN、Fastly、Verizon、Stackpach、AkamaiなどのCDN比較マトリックス。
    • CDN Perfは、毎日3億件のテストを収集して分析することにより、CDNのクエリ速度を測定します。すべての結果は、世界中のユーザーからのRUMデータに基づいています。 DNSパフォーマンスの比較とクラウドパフォーマンスの比較も確認してください。
    • CDN Planet Guidesは、Serve Stale、Purge、Origin Shield、Prefetch、Compressionなどの特定のトピックに関するCDNの概要を提供します。
    • Webアルマナック:CDNの採用と使用法は、トップCDNプロバイダー、それらのRTTおよびTLS管理、TLSネゴシエーション時間、HTTP / 2採用などに関する洞察を提供します。 (残念ながら、データは2019年のもののみです)。

資産の最適化

  1. プレーンテキストの圧縮にはBrotliを使用します。
    2015年、Googleは新しいオープンソースのロスレスデータ形式であるBrotliを導入しました。これは、現在すべての最新のブラウザでサポートされています。 Brotli用のエンコーダーとデコーダーを実装するオープンソースのBrotliライブラリには、エンコーダー用に11の事前定義された品質レベルがあり、品質レベルが高いほど、より良い圧縮率と引き換えにより多くのCPUが必要になります。 圧縮が遅いと、最終的には圧縮率が高くなりますが、それでもBrotliは高速に解凍します。 圧縮レベル4のBrotliは、Gzipよりも小さく、圧縮速度も速いことに注意してください。

    実際には、BrotliはGzipよりもはるかに効果的であるように見えます。 意見や経験は異なりますが、サイトがすでにGzipで最適化されている場合は、サイズの縮小とFCPのタイミングで少なくとも1桁の改善、せいぜい2桁の改善が期待できます。 また、サイトのBrotli圧縮の節約を見積もることもできます。

    ブラウザは、ユーザーがHTTPS経由でWebサイトにアクセスしている場合にのみBrotliを受け入れます。 Brotliは広くサポートされており、多くのCDN(Akamai、Netlify Edge、AWS、KeyCDN、Fastly(現在はパススルーとしてのみ)、Cloudflare、CDN77)をサポートしており、まだサポートしていないCDNでもBrotliを有効にできます(サービスワーカーと)。

    欠点は、Brotliを使用してすべてのアセットを高圧縮レベルで圧縮するのはコストがかかるため、多くのホスティングプロバイダーは、コストのオーバーヘッドが大きいという理由だけで、Brotliをフルスケールで使用できないことです。 実際、最高レベルの圧縮では、Brotliは非常に遅いため、サーバーがアセットを動的に圧縮するのを待機するときにサーバーが応答の送信を開始するのにかかる時間によって、ファイルサイズの潜在的な増加が無効になる可能性があります。 (ただし、ビルド時間中に静的圧縮を使用する時間がある場合は、もちろん、より高い圧縮設定が推奨されます。)

    最小、平均、および90パーセンタイルの3つの異なるバックエンド時間にわたるさまざまな圧縮方法を示すウィスカチャートとして示される比較
    さまざまな圧縮方法のバックエンド時間の比較。 当然のことながら、Brotliはgzipよりも低速です(今のところ)。 (大プレビュー)

    ただし、これは変更される可能性があります。 Brotliファイル形式には、組み込みの静的辞書が含まれており、複数の言語のさまざまな文字列を含むことに加えて、それらの単語に複数の変換を適用するオプションもサポートしているため、汎用性が向上します。 彼の研究で、Felix Hanauは、「デフォルトよりも特殊な辞書のサブセット」を使用し、 Content-Typeヘッダーを使用してコンプレッサーに、 HTML、JavaScriptまたはCSSの辞書。 その結果、「辞書の使用を制限したアプローチを使用して、高圧縮レベルでWebコンテンツを圧縮した場合、パフォーマンスへの影響はごくわずかです(通常の12%に比べてCPUが1%から3%多くなります)」。

    レベル5でBrotli削減辞書を使用した圧縮ゲインを示す棒グラフ
    改善された辞書アプローチにより、1%から3%多くのCPUを使用しながら、より高い圧縮レベルでアセットをより高速に圧縮できます。 通常、圧縮レベル6が5を超えると、CPU使用率が最大12%増加します。 (大プレビュー)

    さらに、Elena Kirilenkoの調査により、以前の圧縮アーティファクトを使用して、高速で効率的なBrotli再圧縮を実現できます。 Elena氏によると、「Brotliを介してアセットを圧縮し、動的コンテンツをオンザフライで圧縮しようとすると、コンテンツが事前に利用可能なコンテンツに似ているため、圧縮時間の大幅な改善を実現できます。 「」

    どのくらいの頻度でそうですか? たとえば、 JavaScriptバンドルサブセットの配信(たとえば、コードの一部がクライアントにすでにキャッシュされている場合、またはWebBundleで提供される動的バンドルを使用する場合)。 または、既知の高度なテンプレートに基づくダイナミックHTML、または動的にサブセット化されたWOFF2フォントを使用します。 Elenaによると、コンテンツの10%を削除すると、圧縮率が5.3%向上し、圧縮速度が39%向上します。また、コンテンツの50%を削除すると、圧縮率が3.2%向上し、圧縮率が26%向上します。

    Brotliの圧縮は向上しているため、静的アセットを動的に圧縮するコストを回避できれば、努力する価値は間違いありません。 言うまでもなく、Brotliは、HTML、CSS、SVG、JavaScript、JSONなどの任意のプレーンテキストペイロードに使用できます。

    :2021年初頭の時点で、HTTP応答の約60%がテキストベースの圧縮なしで配信され、30.82%がGzipで圧縮され、9.1%がBrotliで圧縮されています(モバイルとデスクトップの両方)。 たとえば、Angularページの23.4%は圧縮されていません(gzipまたはBrotliを介して)。 しかし、多くの場合、圧縮をオンにすることは、スイッチを押すだけでパフォーマンスを向上させる最も簡単な方法の1つです。

    戦略は? 静的アセットを最高レベルのBrotli + Gzipで事前圧縮し、(動的)HTMLをレベル4〜6のBrotliでオンザフライで圧縮します。 サーバーがBrotliまたはGzipのコンテンツネゴシエーションを適切に処理することを確認してください。

Web Almanax2020レポートによるHTTPリクエストの圧縮アルゴリズムを示す棒グラフ
2020年に圧縮されて提供されるリソースのうち、22.59%がBrotliで圧縮されています。 約77.39%がgzipで圧縮されています。 (画像ソース:Webアルマナック:圧縮)(大プレビュー)
  1. アダプティブメディアローディングとクライアントヒントを使用していますか?
    これは古いニュースの世界から来ていますが、 srcsetsizes 、および<picture>要素を含むレスポンシブ画像を使用することを常にお勧めします。 特にメディアフットプリントが大きいサイトの場合、アダプティブメディアローディング(この例ではReact + Next.js)を使用してさらに一歩進め、低速のネットワークと低メモリデバイスに軽いエクスペリエンスを提供し、高速のネットワークと高速に完全なエクスペリエンスを提供できます-メモリデバイス。 Reactのコンテキストでは、サーバー上のクライアントヒントとクライアント上のreact-adaptive-hooksを使用してこれを実現できます。

    レスポンシブ画像の未来は、クライアントヒントの採用が広がるにつれて劇的に変わる可能性があります。 クライアントヒントは、HTTPリクエストヘッダーフィールドです。たとえば、 DPRViewport-WidthWidthSave-DataAccept (画像形式の設定を指定するため)などです。 それらは、ユーザーのブラウザ、画面、接続などの詳細についてサーバーに通知することになっています。

    その結果、サーバーは適切なサイズの画像をレイアウトに入力する方法を決定し、これらの画像のみを目的の形式で提供できます。 クライアントヒントを使用して、リソースの選択をHTMLマークアップから、クライアントとサーバー間の要求/応答ネゴシエーションに移動します。

    ネットワーク機能に応じてユーザーに異なる解像度を送信することにより、アダプティブメディアサービングをどのように使用できるかを示す図
    使用中のアダプティブメディア。 オフラインのユーザーにはテキスト、2Gユーザーには低解像度の画像、3Gユーザーには高解像度の画像、4GユーザーにはHDビデオを含むプレースホルダーを送信します。 20ドルのフィーチャーフォンでウェブページをすばやく読み込む。 (大プレビュー)

    Ilya Grigorikがしばらく前に指摘したように、クライアントのヒントが全体像を完成させます。これらはレスポンシブ画像に代わるものではありません。 「 <picture>要素は、HTMLマークアップで必要なアートディレクションコントロールを提供します。クライアントヒントは、リソース選択の自動化を可能にする結果の画像リクエストに注釈を提供します。ServiceWorkerは、クライアントに完全なリクエストおよびレスポンス管理機能を提供します。」

    たとえば、サービスワーカーは、リクエストに新しいクライアントヒントヘッダー値を追加したり、URLを書き換えて画像リクエストをCDNにポイントしたり、接続性やユーザー設定に基づいて応答を調整したりできます。これは、画像アセットだけでなく、他のほとんどすべてのリクエストについても同様です。

    クライアントヒントをサポートするクライアントの場合、画像で42%のバイト節約、70パーセンタイル以上で1MB以上のバイト削減を測定できます。 Smashing Magazineでは、19〜32%の改善も測定できました。 クライアントヒントはChromiumベースのブラウザでサポートされていますが、Firefoxではまだ検討中です。

    ただし、クライアントヒントに通常のレスポンシブ画像マークアップと<meta>タグの両方を指定すると、サポートするブラウザがレスポンシブ画像マークアップを評価し、クライアントヒントHTTPヘッダーを使用して適切な画像ソースを要求します。

  2. 背景画像にレスポンシブ画像を使用していますか?
    きっと! Safari 14およびFirefoxを除くほとんどの最新ブラウザでサポートされるようになったimage-setを使用すると、レスポンシブな背景画像も提供できます。

    background-image: url("fallback.jpg"); background-image: image-set( "photo-small.jpg" 1x, "photo-large.jpg" 2x, "photo-print.jpg" 600dpi);

    基本的に、 1x記述子を使用した低解像度の背景画像、 2x記述子を使用した高解像度画像、さらには600dpi記述子を使用した印刷品質の画像を条件付きで提供できます。 ただし、注意してください。ブラウザは支援技術に背景画像に関する特別な情報を提供しないため、理想的にはこれらの写真は単なる装飾にすぎません。

  3. WebPを使用していますか?
    多くの場合、画像圧縮はすぐに成功すると考えられていますが、実際にはまだ十分に活用されていません。 もちろん、画像はレンダリングをブロックしませんが、LCPスコアの低下に大きく影響します。また、多くの場合、画像は、使用しているデバイスに対して重すぎたり大きすぎたりします。

    したがって、少なくとも、画像にWebP形式を使用して探索することができます。 実際、WebPの物語は、AppleがSafari 14でWebPのサポートを追加することで、昨年終わりに近づいています。したがって、長年の議論と議論の末、今日の時点で、WebPはすべての最新ブラウザーでサポートされています。 したがって、必要に応じて<picture>要素とJPEGフォールバックを使用して(Andreas Bovensのコードスニペットを参照)、またはコンテンツネゴシエーションを使用して( Acceptヘッダーを使用して)WebP画像を提供できます。

    ただし、WebPには欠点があります。 WebP画像のファイルサイズは同等のGuetzliやZopfliと比較されますが、この形式はJPEGのようなプログレッシブレンダリングをサポートしていません。そのため、WebP画像はネットワークを介して高速化される可能性がありますが、ユーザーは古き良きJPEGで完成した画像をより速く表示できます。 JPEGを使用すると、WebPの場合のように半分空の画像を表示するのではなく、データの半分または4分の1で「まともな」ユーザーエクスペリエンスを提供し、残りを後で読み込むことができます。

    決定は、何を求めているかによって異なります。WebPを使用するとペイロードが減り、JPEGを使用すると知覚されるパフォーマンスが向上します。 WebPの詳細については、GoogleのPascalMassiminoによるWebPRewindトークをご覧ください。

    WebPへの変換には、WebP Converter、cwebp、またはlibwebpを使用できます。 Ire Aderinokunには、画像をWebPに変換するための非常に詳細なチュートリアルもあります。また、最新の画像形式を採用することについてのJoshComeauも同様です。

    PascalMassiminoの講演「Imageready:webprewind」に使用されたスライド
    WebPについての徹底的な話:PascalMassiminoによるWebP巻き戻し。 (大プレビュー)

    SketchはネイティブにWebPをサポートしており、Photoshop用のWebPプラグインを使用してWebP画像をPhotoshopからエクスポートできます。 ただし、他のオプションも利用できます。

    WordPressまたはJoomlaを使用している場合は、WordPress用のOptimusやCache Enabler、Joomla独自のサポートされている拡張機能(Cody Arsenault経由)など、WebPのサポートを簡単に実装するのに役立つ拡張機能があります。 <picture>要素をReact、スタイル付きコンポーネント、またはgatsby-imageで抽象化することもできます。

    ああ—恥知らずなプラグ! — Jeremy Wagnerは、WebPに関するSmashingの本を出版しました。これは、WebPに関するすべてのことに興味があるかどうかを確認することをお勧めします。

  4. AVIFを使用していますか?
    あなたは大きなニュースを聞いたことがあるかもしれません:AVIFが上陸しました。 これは、AV1ビデオのキーフレームから派生した新しい画像形式です。 これは、非可逆および可逆圧縮、アニメーション、非可逆アルファチャネルをサポートし、シャープな線と単色(JPEGの問題でした)を処理できると同時に、両方でより良い結果を提供する、オープンでロイヤリティフリーの形式です。

    実際、WebPやJPEGと比較して、AVIFのパフォーマンスは大幅に向上し、同じDSSIMでファイルサイズの中央値を最大50%節約できます(人間の視覚に近いアルゴリズムを使用した2つ以上の画像間の(非)類似性)。 実際、Malte Ublは、画像の読み込みの最適化に関する徹底的な投稿で、AVIFは「非常に一貫して非常に重要な点でJPEGを上回っています。これは、常にJPEGよりも小さい画像を生成するわけではなく、実際にはネットである可能性があるWebPとは異なります。プログレッシブローディングのサポートの欠如による損失。」

    プログレッシブエンハンスメントとしてAVIFを示すコードスニペット
    AVIFをプログレッシブエンハンスメントとして使用して、WebP、JPEG、またはPNGを古いブラウザーに配信できます。 (大きなプレビュー)。 以下のプレーンテキストビューを参照してください。

    皮肉なことに、AVIFは大規模なSVGよりも優れたパフォーマンスを発揮しますが、もちろんSVGの代わりと見なすべきではありません。 また、HDRカラーサポートをサポートする最初の画像形式の1つです。 より高い輝度、カラービット深度、および色域を提供します。 唯一の欠点は、現在AVIFがプログレッシブ画像のデコードをサポートしていないことです(まだ?)。Brotliと同様に、デコードは高速ですが、高圧縮率のエンコードは現在非常に低速です。

    AVIFは現在Chrome、Firefox、Operaでサポートされており、Safariでのサポートは間もなく開始される予定です(AppleはAV1を作成したグループのメンバーであるため)。

    最近の画像を提供するための最良の方法は何ですか? イラストやベクター画像の場合、(圧縮された)SVGが間違いなく最良の選択です。 写真の場合、 picture要素を使用したコンテンツネゴシエーションメソッドを使用します。 AVIFがサポートされている場合は、AVIFイメージを送信します。 そうでない場合は、最初にWebPにフォールバックし、WebPもサポートされていない場合は、フォールバックとしてJPEGまたはPNGに切り替えます(必要に応じて@media条件を適用します)。

    <picture> <source type="image/avif"> <source type="image/webp"> <img src="image.jpg" alt="Photo" width="450" height="350"> </picture>

    率直に言って、 picture要素内でいくつかの条件を使用する可能性が高くなります。

    <picture> <source type="image/avif" /> <source type="image/webp" /> <source type="image/jpeg" /> <img src="fallback-image.jpg" alt="Photo" width="450" height="350"> </picture>
    <picture> <source type="image/avif" /> <source type="image/webp" /> <source type="image/jpeg" /> <img src="fallback-image.jpg" alt="Photo" width="450" height="350"> </picture>

    動きを少なくすることを選択し、 prefers-reduced-motionを使用する顧客のために、アニメーション画像を静止画像と交換することで、さらに先に進むことができます。

    <picture> <source media="(prefers-reduced-motion: reduce)" type="image/avif"></source> <source media="(prefers-reduced-motion: reduce)" type="image/jpeg"></source> <source type="image/avif"></source> <img src="motion.jpg" alt="Animated AVIF"> </picture>
    <picture> <source media="(prefers-reduced-motion: reduce)" type="image/avif"></source> <source media="(prefers-reduced-motion: reduce)" type="image/jpeg"></source> <source type="image/avif"></source> <img src="motion.jpg" alt="Animated AVIF"> </picture>

    数か月の間に、AVIFはかなりの牽引力を獲得しました。

    • DevToolsの[レンダリング]パネルでWebP / AVIFフォールバックをテストできます。
    • Squoosh、AVIF.io、libavifを使用して、AVIFファイルのエンコード、デコード、圧縮、変換を行うことができます。
    • ワーカーでAVIFファイルをデコードし、結果をキャンバスに表示するJakeArchibaldのAVIFPreactコンポーネントを使用できます。
    • サポートしているブラウザにのみAVIFを配信するために、PostCSSプラグインと315Bスクリプトを使用して、CSS宣言でAVIFを使用できます。
    • CSSとCloudlareWorkersを使用して新しい画像形式を段階的に提供し、返されたHTMLドキュメントを動的に変更し、 acceptヘッダーから情報を推測して、必要に応じてwebp/avifなどのクラスを追加できます。
    • AVIFはすでにCloudinaryで利用可能であり(使用制限あり)、Cloudflareは画像のサイズ変更でAVIFをサポートしており、NetlifyのカスタムAVIFヘッダーでAVIFを有効にすることができます。
    • アニメーションに関しては、AVIFはSafariの<img src=mp4>と同様に機能し、GIFやWebP全体を上回っていますが、MP4の方が優れています。
    • 一般に、アニメーションの場合、Chromiumベースのブラウザが<img src=mp4>をサポートすると仮定すると、AVC1(h264)> HVC1> WebP> AVIF> GIFです。
    • AVIFの詳細については、NetflixのAdityaMavlankarによるAVIFfor Next Generation Image Codingトーク、およびCloudflareのKornelLesinskiによるAVIFImageFormatトークをご覧ください。
    • すべてのAVIFの優れたリファレンス:AVIFに関するJakeArchibaldの包括的な投稿が上陸しました。

    では、将来のAVIFはそうですか? Jon Sneyersは同意しません。AVIFのパフォーマンスは、GoogleとCloudinaryによって開発されたもう1つの無料のオープンフォーマットであるJPEG XLよりも60%劣っています。 実際、JPEGXLのパフォーマンスは全体的にはるかに優れているようです。 ただし、JPEG XLはまだ標準化の最終段階にあり、どのブラウザでもまだ機能していません。 (古き良きInternet Explorerから9回提供されているMicrosoftのJPEG-XRと混同しないでください)。

レスポンシブ画像ブレークポイントジェネレータ
Responsive Image Breakpoints Generatorは、画像とマークアップの生成を自動化します。
  1. JPEG / PNG / SVGは適切に最適化されていますか?
    ヒーロー画像が非常に高速に読み込まれることが重要なランディングページで作業している場合は、JPEGがプログレッシブであり、mozJPEG(スキャンレベルを操作することでレンダリング開始時間を改善する)またはGoogleのオープンソースであるGuetzliで圧縮されていることを確認してください知覚パフォーマンスに焦点を当て、ZopfliとWebPからの学習を利用するエンコーダー。 唯一の欠点:処理時間が遅い(メガピクセルあたり1分のCPU)。

    PNGの場合はPingoを使用でき、SVGの場合はSVGOまたはSVGOMGを使用できます。 また、WebサイトからすべてのSVGアセットをすばやくプレビューしてコピーまたはダウンロードする必要がある場合は、svg-grabberでもそれを実行できます。

    すべての画像最適化の記事でそれが述べられていますが、ベクターアセットをクリーンでタイトに保つことは常に言及する価値があります。 未使用のアセットをクリーンアップし、不要なメタデータを削除し、アートワーク(したがってSVGコード)のパスポイントの数を減らしてください。 (ありがとう、ジェレミー!

    ただし、便利なオンラインツールもあります。

    • Squooshを使用して、最適な圧縮レベル(非可逆または可逆)で画像を圧縮、サイズ変更、および操作します。
    • Guetzli.itを使用して、GuetzliでJPEG画像を圧縮および最適化します。これは、シャープなエッジと単色の画像に適しています(ただし、かなり遅くなる可能性があります))。
    • Responsive Image Breakpoints GeneratorまたはCloudinaryやImgixなどのサービスを使用して、画像の最適化を自動化します。 また、多くの場合、 srcsetsizesだけを使用すると、大きなメリットが得られます。
    • レスポンシブマークアップの効率を確認するには、ビューポートサイズとデバイスのピクセル比全体の効率を測定するコマンドラインツールであるイメージングヒープを使用できます。
    • GitHubワークフローに自動画像圧縮を追加できるため、圧縮されていない状態で画像が本番環境に到達することはありません。 このアクションでは、PNGおよびJPGで機能するmozjpegおよびlibvipsを使用します。
    • ストレージを内部的に最適化するには、Dropboxの新しいLepton形式を使用して、JPEGを平均22%ロスレスで圧縮できます。
    • プレースホルダー画像を早く表示したい場合は、BlurHashを使用してください。 BlurHashは画像を取得し、この画像のプレースホルダーを表す短い文字列(20〜30文字のみ!)を提供します。 文字列は十分に短いため、JSONオブジェクトのフィールドとして簡単に追加できます。
    左側に画像プレースホルダーがない場合と右側にプレースホルダーがある場合のインターフェイスの比較
    BlurHashは、画像のプレースホルダーを小さくコンパクトに表現したものです。 (大プレビュー)

    画像を最適化するだけではうまくいかない場合があります。 重要な画像のレンダリングを開始するために必要な時間を改善するには、重要度の低い画像を遅延ロードし、重要な画像が既にレンダリングされた後にロードするスクリプトを延期します。 最も防弾の方法は、ハイブリッド遅延読み込みです。ネイティブの遅延読み込みとlazyloadを利用する場合、ユーザーの操作によってトリガーされる可視性の変化を検出するライブラリです(IntersectionObserverについては後で説明します)。 さらに:

    • 重要な画像をプリロードすることを検討してください。そうすれば、ブラウザはそれらを遅すぎて検出しません。 背景画像の場合、それよりもさらに積極的にしたい場合は、 <img src>を使用して画像を通常の画像として追加し、画面から非表示にすることができます。
    • メディアクエリに応じて異なる画像表示サイズを指定して、サイズ属性で画像を交換することを検討してください。たとえば、拡大鏡コンポーネントでソースを交換するためにsizesを操作します。
    • 前景画像と背景画像の予期しないダウンロードを防ぐために、画像のダウンロードの不整合を確認してください。 デフォルトで読み込まれるが、表示されない可能性のある画像(カルーセル、アコーディオン、画像ギャラリーなど)に注意してください。
    • 画像のwidthheightは必ず設定してください。 CSSのaspect-ratioプロパティとintrinsicsize属性に注意してください。これにより、画像のアスペクト比とサイズを設定できるため、ブラウザは事前定義されたレイアウトスロットを早期に予約して、ページの読み込み中にレイアウトがジャンプしないようにすることができます。
    エディターで使用されているパディングトップ要素とアスペクト比要素を示すコードのスクリーンショット
    ブラウザにアスペクト比が表示されるようになり、今では数週間または数か月の問題になるはずです。 Safariテクニカルプレビュー118ではすでに。 現在、FirefoxとChromeのフラグの背後にあります。 (大プレビュー)

    冒険心があれば、Edgeワーカー(基本的にはCDNにあるリアルタイムフィルター)を使用してHTTP / 2ストリームを切り刻み、再配置して、ネットワーク経由で画像をより高速に送信できます。 エッジワーカーは、制御可能なチャンクを使用するJavaScriptストリームを使用するため(基本的には、ストリーミング応答を変更できるCDNエッジで実行されるJavaScriptです)、画像の配信を制御できます。

    サービスワーカーの場合、ネットワーク上にあるものを制御できないため手遅れになりますが、エッジワーカーでは機能します。 したがって、特定のランディングページ用に段階的に保存された静的JPEGの上でそれらを使用できます。

    さまざまなビューポートサイズとデバイスのピクセル比の表を示すイメージングヒープコマンドラインツールのスクリーンショット
    ビューポートサイズとデバイスのピクセル比全体の効率を測定するコマンドラインツールであるイメージングヒープによるサンプル出力。 (画像ソース)(大きなプレビュー)

    十分じゃない? また、複数の背景画像の手法を使用して、画像の知覚パフォーマンスを向上させることもできます。 コントラストで遊んだり、不要な詳細をぼかしたり(または色を削除したり)すると、ファイルサイズも小さくなる可能性があることに注意してください。 ああ、品質を落とさずに小さな写真を拡大する必要がありますか? Letsenhance.ioの使用を検討してください。

    これまでのところ、これらの最適化は基本的なことだけをカバーしています。 Addy Osmaniは、画像圧縮とカラーマネジメントの詳細を深く掘り下げたEssential ImageOptimizationに関する非常に詳細なガイドを公開しています。 たとえば、画像の不要な部分を(ガウスぼかしフィルターを適用して)ぼかしてファイルサイズを小さくしたり、最終的には色を削除したり、画像を白黒に変えてサイズをさらに小さくしたりすることができます。 。 背景画像の場合、Photoshopから0〜10%の品質で写真をエクスポートすることも絶対に許容できます。

    Smashing Magazineでは、画像名に接尾辞-optを使用します—たとえば、 brotli-compression-opt.png ; 画像にその接尾辞が含まれている場合は常に、チームの全員が画像がすでに最適化されていることを知っています。

    ああ、WebでJPEG-XRを使用しないでください—「CPUでソフトウェア側のJPEG-XRをデコードする処理は無効になり、特にSPAのコンテキストでは、バイトサイズの節約による潜在的なプラスの影響を上回ります」( Cloudinary / GoogleのJPEGXLと混同することもあります)。

アニメーションGIFをビデオ要素に置き換えて80%以上節約
Addy Osmaniは、アニメーションGIFをループインラインビデオに置き換えることをお勧めします。 ファイルサイズの違いは顕著です(80%の節約)。 (大プレビュー)
  1. ビデオは適切に最適化されていますか?
    これまで画像について説明してきましたが、古き良きGIFについての会話は避けました。 私たちがGIFを愛しているにもかかわらず、(少なくとも私たちのWebサイトやアプリでは)GIFを永久に放棄する時が来ました。 レンダリングパフォーマンスと帯域幅の両方に影響を与える重いアニメーションGIFをロードする代わりに、アニメーションWebP(GIFはフォールバック)に切り替えるか、ループHTML5ビデオに完全に置き換えることをお勧めします。

    画像とは異なり、ブラウザは<video>コンテンツをプリロードしませんが、HTML5ビデオはGIFよりもはるかに軽量で小さい傾向があります。 オプションではありませんか? 少なくとも、不可逆GIF、gifsicle、またはgiflossyを使用してGIFに不可逆圧縮を追加できます。

    Colin Bendellによるテストでは、Safari Technology Previewのimgタグ内のインラインビデオは、ファイルサイズの一部であることに加えて、同等のGIFよりも少なくとも20倍速く、7倍速くデコードされることが示されています。 ただし、他のブラウザではサポートされていません。

    良いニュースの地では、ビデオフォーマットは何年にもわたって大幅に進歩しています。 長い間、WebMがそれらすべてを支配するフォーマットになり、WebP(基本的にはWebMビデオコンテナ内の1つの静止画像)が古い画像フォーマットの代わりになることを望んでいました。 確かに、Safariは現在WebPをサポートしていますが、最近WebPとWebMがサポートを獲得しているにもかかわらず、ブレークスルーは実際には起こりませんでした。

    それでも、最新のブラウザのほとんどにWebMを使用できます。

    <!-- By Houssein Djirdeh. https://web.dev/replace-gifs-with-videos/ --> <!-- A common scenartio: MP4 with a WEBM fallback. --> <video autoplay loop muted playsinline> <source src="my-animation.webm" type="video/webm"> <source src="my-animation.mp4" type="video/mp4"> </video>

    しかし、おそらく私たちはそれを完全に再考することができます。 2018年、Alliance of Open Mediaは、 AV1と呼ばれる新しい有望なビデオ形式をリリースしました。 AV1はH.265コーデック(H.264の進化形)と同様の圧縮を備えていますが、後者とは異なり、AV1は無料です。 H.265ライセンスの価格設定により、ブラウザベンダーは、代わりに同等のパフォーマンスを発揮するAV1を採用するようになりました。AV1(H.265と同様)は、WebMの2倍の圧縮率を実現します。

    AV1ロゴ2018
    AV1は、Web上のビデオの究極の標準になる可能性が高いです。 (画像クレジット:Wikimedia.org)(大プレビュー)

    実際、Appleは現在HEIF形式とHEVC(H.265)を使用しており、最新のiOSのすべての写真とビデオはJPEGではなくこれらの形式で保存されます。 HEIFとHEVC(H.265)は(まだ?)Webに適切に公開されていませんが、AV1は公開されており、ブラウザーのサポートを受けています。 したがって、すべてのブラウザベンダーが参加しているように見えるため、 <video>タグにAV1ソースを追加することは合理的です。

    現在、最も広く使用され、サポートされているエンコーディングはH.264であり、MP4ファイルによって提供されます。したがって、ファイルを提供する前に、MP4がマルチパスエンコーディングで処理され、frei0r iirblur効果(該当する場合)でぼやけていることを確認してください。サーバーがバイトサービングを受け入れている間、moovアトムメタデータはファイルの先頭に移動されます。 Boris Schapiraは、FFmpegがビデオを最大限に最適化するための正確な手順を提供します。 もちろん、代わりにWebM形式を提供することも役立ちます。

    ビデオのレンダリングをより速く開始する必要がありますが、ビデオファイルはまだ大きすぎますか? たとえば、ランディングページに大きな背景動画があるときはいつでも? 使用する一般的な手法は、最初に静止画像として最初のフレームを表示するか、ビデオの一部として解釈できる高度に最適化された短いループセグメントを表示してから、ビデオが十分にバッファリングされるたびに再生を開始することです。実際のビデオ。 Doug Sillarsは、その場合に役立つ可能性のあるバックグラウンドビデオパフォーマンスの詳細なガイドを作成しました。 (ありがとう、Guy Podjarny! )。

    上記のシナリオでは、レスポンシブポスター画像を提供することをお勧めします。 デフォルトでは、 video要素はポスターとして1つの画像のみを許可しますが、これは必ずしも最適ではありません。 レスポンシブビデオポスターを使用できます。これは、さまざまな画面にさまざまなポスター画像を使用できるJavaScriptライブラリであり、ビデオプレースホルダーのトランジションオーバーレイと完全なスタイリングコントロールも追加できます。

    調査によると、ビデオストリームの品質は視聴者の行動に影響を与えます。 実際、起動遅延が約2秒を超えると、視聴者は動画を放棄し始めます。 そのポイントを超えると、遅延が1秒増加すると、放棄率が約5.8%増加します。 したがって、ビデオの開始時間の中央値が12.8秒であり、ビデオの40%に少なくとも1つのストールがあり、20%に少なくとも2秒のビデオ再生が停止していることは驚くべきことではありません。 実際、ネットワークがコンテンツを提供できるよりも速くビデオが再生されるため、3Gではビデオのストールは避けられません。

    それで、解決策は何ですか? 通常、小さな画面のデバイスは、デスクトップに提供している720pと1080pを処理できません。 Doug Sillarsによると、ビデオの小さいバージョンを作成し、Javascriptを使用して小さい画面のソースを検出して、これらのデバイスでの高速でスムーズな再生を保証することができます。 または、ストリーミングビデオを使用することもできます。 HLSビデオストリームは、適切なサイズのビデオをデバイスに配信します。これにより、画面ごとに異なるビデオを作成する必要がなくなります。 また、ネットワーク速度をネゴシエートし、使用しているネットワークの速度に合わせてビデオビットレートを調整します。

    帯域幅の浪費を避けるために、実際にビデオをうまく再生できるデバイスのビデオソースのみを追加することができました。 または、 videoタグからautoplay属性を完全に削除し、JavaScriptを使用してより大きな画面のautoplayを挿入することもできます。 さらに、 videopreload="none"を追加して、実際にファイルが必要になるまでビデオファイルをダウンロードしないようにブラウザに指示する必要があります。

    <!-- Based on Doug Sillars's post. https://dougsillars.com/2020/01/06/hiding-videos-on-the-mbile-web/ --> <video preload="none" playsinline muted loop width="1920" height="1080" poster="poster.jpg"> <source src="video.webm" type="video/webm"> <source src="video.mp4" type="video/mp4"> </video>

    次に、AV1を実際にサポートするブラウザを具体的にターゲットにできます。

    <!-- Based on Doug Sillars's post. https://dougsillars.com/2020/01/06/hiding-videos-on-the-mbile-web/ --> <video preload="none" playsinline muted loop width="1920" height="1080" poster="poster.jpg"> <source src="video.av1.mp4" type="video/mp4; codecs=av01.0.05M.08"> <source src="video.hevc.mp4" type="video/mp4; codecs=hevc"> <source src="video.webm" type="video/webm"> <source src="video.mp4" type="video/mp4"> </video>

    次に、特定のしきい値( autoplayなど)を超えて自動再生を再度追加できます。

    /* By Doug Sillars. https://dougsillars.com/2020/01/06/hiding-videos-on-the-mbile-web/ */ <script> window.onload = addAutoplay(); var videoLocation = document.getElementById("hero-video"); function addAutoplay() { if(window.innerWidth > 1000){ videoLocation.setAttribute("autoplay",""); }; } </script>
    Alcatel 1X、Moto G、Moto G4、MotoE、Nexus 5、OnePlus 5の3G、ケーブル、LTE、ネイティブなど、デバイスとネットワークの速度ごとの小さなtme(ms)を示す棒グラフ
    デバイスおよびネットワーク速度ごとのストールの数。 より高速なネットワーク上のより高速なデバイスには、実質的にストールがありません。 ダグシラーズの調査によると。 (大プレビュー)

    ビデオ再生パフォーマンスはそれ自体がストーリーです。詳細を知りたい場合は、ビデオ配信メトリックの詳細を含む、ビデオおよびビデオ配信のベストプラクティスの現状に関する別のダグシラーズのシリーズをご覧ください。 、ビデオのプリロード、圧縮、ストリーミング。 最後に、StreamまたはNotを使用して、ビデオストリーミングがどの程度遅くなるかまたは速くなるかを確認できます。

マインドマップグラフとして表示されるZachLeathermanのフォント読み込み戦略に関する包括的なガイド
Zach Leathermanのフォント読み込み戦略に関する包括的なガイドには、Webフォントの配信を改善するための多数のオプションが用意されています。
  1. Webフォントの配信は最適化されていますか?
    質問する価値のある最初の質問は、最初にUIシステムフォントの使用を回避できるかどうかです。さまざまなプラットフォームで正しく表示されることを再確認する必要があります。 そうでない場合は、提供しているWebフォントに、使用されていないグリフや追加の機能やウェイトが含まれている可能性が高くなります。 書体ファウンドリにWebフォントのサブセット化を依頼するか、オープンソースフォントを使用している場合は、GlyphhangerまたはFontsquirrelを使用して独自にサブセット化することができます。 Peter Mullerのサブフォントを使用してワークフロー全体を自動化することもできます。これは、ページを静的に分析して最適なWeb​​フォントサブセットを生成し、それらをページに挿入するコマンドラインツールです。

    WOFF2のサポートは素晴らしく、WOFFをサポートしていないブラウザーのフォールバックとして使用できます。あるいは、レガシーブラウザーにシステムフォントを提供することもできます。 Webフォントの読み込みには非常に多くのオプションがあり、ZachLeathermanの「フォント読み込み戦略の包括的なガイド」(コードスニペットはWebフォント読み込みレシピとしても利用可能)から戦略の1つを選択できます。

    おそらく、今日検討すべきより良いオプションは、 preloadを使用したクリティカルFOFTと「妥協」方式です。 どちらも2段階のレンダリングを使用してWebフォントを段階的に配信します。最初に、Webフォントを使用してページを高速かつ正確にレンダリングするために必要な小さなスーパーサブセットを使用し、次にファミリの残りの部分を非同期でロードします。 違いは、「妥協」手法は、フォントロードイベントがサポートされていない場合にのみポリフィルを非同期にロードするため、デフォルトでポリフィルをロードする必要がないことです。 迅速な勝利が必要ですか? Zach Leathermanには、フォントを整理するための23分間の簡単なチュートリアルとケーススタディがあります。

    一般に、 preloadリソースヒントを使用してフォントをプリロードすることをお勧めしますが、マークアップでは、重要なCSSおよびJavaScriptへのリンクのにヒントを含めます。 preloadを使用すると、優先順位のパズルが発生するため、外部ブロッキングスクリプトの直前にrel="preload"要素をDOMに挿入することを検討してください。 Andy Daviesによると、「スクリプトを使用して挿入されたリソースは、スクリプトが実行されるまでブラウザーから隠されます。この動作を使用して、ブラウザーがpreloadヒントを検出するのを遅らせることができます。」 そうしないと、フォントの読み込みに最初のレンダリング時にコストがかかります。

    スライド93のスクリーンショットは、「メトリクスの優先順位付け:各ファミリの1つをプリロードする」というタイトルが横に付いた画像の2つの例を示しています
    すべてが重要であるとき、何も重要ではありません。 各ファミリのフォントを1つだけ、または最大2つプリロードします。 (画像クレジット:Zach Leatherman –スライド93)(大きなプレビュー)

    選択して最も重要なファイルを選択することをお勧めします。たとえば、レンダリングに不可欠なファイルや、目に見えて混乱を招くテキストのリフローを回避するのに役立つファイルなどです。 一般に、Zachは、各ファミリの1つまたは2つのフォントをプリロードすることをお勧めします。重要度が低い場合は、フォントのロードを遅らせることも理にかなっています。

    @font-faceルールでフォントfont-familyを定義するときに、 local()値(名前でローカルフォントを参照する)を使用することが非常に一般的になっています。

     /* Warning! Not a good idea! */ @font-face { font-family: Open Sans; src: local('Open Sans Regular'), local('OpenSans-Regular'), url('opensans.woff2') format ('woff2'), url('opensans.woff') format('woff'); }

    アイデアは合理的です。OpenSansなどの人気のあるオープンソースフォントには、一部のドライバーやアプリがプリインストールされているため、フォントがローカルで利用できる場合、ブラウザーはWebフォントをダウンロードする必要がなく、ローカルを表示できます。すぐにフォント。 Bram Steinが指摘したように、「ローカルフォントはWebフォントの名前と一致しますが、同じフォントではない可能性があります。多くのWebフォントは、「デスクトップ」バージョンとは異なります。テキストのレンダリングが異なる場合があり、一部の文字が落ちる場合があります。他のフォントに戻ると、OpenType機能が完全に欠落しているか、行の高さが異なる可能性があります。」

    また、書体は時間の経過とともに進化するため、ローカルにインストールされたバージョンはWebフォントとは大きく異なり、文字の外観も大きく異なる可能性があります。 したがって、Bramによれば、ローカルにインストールされたフォントとWebフォント@font-faceルールに混在させない方がよいとのことです。 Google Fontsはそれに続いて、Robotoに対するAndroidリクエストを除く、すべてのユーザーのCSS結果でlocal()を無効にしました。

    コンテンツが表示されるのを待つのが好きな人はいません。 font-display CSS記述子を使用すると、フォントの読み込み動作を制御し、コンテンツをすぐにfont-display: optionalで)またはほぼすぐに(フォントが正常にダウンロードされる限り、3秒のタイムアウトで)読み取り可能にすることができます。 font-display: swap )。 (まあ、それよりも少し複雑です。)

    ただし、テキストリフローの影響を最小限に抑えたい場合は、 Font Loading API (最新のすべてのブラウザでサポートされています)を使用できます。 具体的には、すべてのフォントについて、 FontFaceオブジェクトを作成し、それらをすべてフェッチしてから、ページに適用することを意味します。 このように、すべてのフォントを非同期でロードしてすべての再描画をグループ化し、フォールバックフォントからWebフォントに1回だけ切り替えます。 32:15から始まるザックの説明とコードスニペットを見てください):

    /* Load two web fonts using JavaScript */ /* Zach Leatherman: https://noti.st/zachleat/KNaZEg/the-five-whys-of-web-font-loading-performance#sWkN4u4 */ // Remove existing @font-face blocks // Create two let font = new FontFace("Noto Serif", /* ... */); let fontBold = new FontFace("Noto Serif, /* ... */); // Load two fonts let fonts = await Promise.all([ font.load(), fontBold.load() ]) // Group repaints and render both fonts at the same time! fonts.forEach(font => documents.fonts.add(font));
    /* Load two web fonts using JavaScript */ /* Zach Leatherman: https://noti.st/zachleat/KNaZEg/the-five-whys-of-web-font-loading-performance#sWkN4u4 */ // Remove existing @font-face blocks // Create two let font = new FontFace("Noto Serif", /* ... */); let fontBold = new FontFace("Noto Serif, /* ... */); // Load two fonts let fonts = await Promise.all([ font.load(), fontBold.load() ]) // Group repaints and render both fonts at the same time! fonts.forEach(font => documents.fonts.add(font));

    Font Loading APIを使用してフォントの非常に早いフェッチを開始するために、AdrianBeceは改行しないスペースnbsp; bodyの上部にあり、 aria-visibility: hiddenおよび.hiddenクラス:

    <body class="no-js"> <!-- ... Website content ... --> <div aria-visibility="hidden" class="hidden"> <!-- There is a non-breaking space here --> </div> <script> document.getElementsByTagName("body")[0].classList.remove("no-js"); </script> </body>
    <body class="no-js"> <!-- ... Website content ... --> <div aria-visibility="hidden" class="hidden"> <!-- There is a non-breaking space here --> </div> <script> document.getElementsByTagName("body")[0].classList.remove("no-js"); </script> </body>

    これは、さまざまな読み込み状態に対してさまざまなフォントファミリが宣言されているCSSに対応しており、フォントが正常に読み込まれると、Font LoadingAPIによって変更がトリガーされます。

    body:not(.wf-merriweather--loaded):not(.no-js) { font-family: [fallback-system-font]; /* Fallback font styles */ } .wf-merriweather--loaded, .no-js { font-family: "[web-font-name]"; /* Webfont styles */ } /* Accessible hiding */ .hidden { position: absolute; overflow: hidden; clip: rect(0 0 0 0); height: 1px; width: 1px; margin: -1px; padding: 0; border: 0; }
    body:not(.wf-merriweather--loaded):not(.no-js) { font-family: [fallback-system-font]; /* Fallback font styles */ } .wf-merriweather--loaded, .no-js { font-family: "[web-font-name]"; /* Webfont styles */ } /* Accessible hiding */ .hidden { position: absolute; overflow: hidden; clip: rect(0 0 0 0); height: 1px; width: 1px; margin: -1px; padding: 0; border: 0; }

    すべての最適化にもかかわらず、なぜLighthouseがレンダリングブロックリソース(フォント)を削除することを提案しているのか疑問に思ったことがある場合は、同じ記事でAdrian Beceが、パフォーマンスの高い非同期フォントであるGatsby Omni Font Loaderとともに、Lighthouseを幸せにするためのいくつかのテクニックを提供します。 Gatsby用のUnstyledText(FOUT)処理プラグインのロードとフラッシュ。

    現在、私たちの多くは、CDNまたはサードパーティのホストを使用してWebフォントをロードしている可能性があります。 一般に、可能であればすべての静的アセットをセルフホストすることをお勧めします。そのため、GoogleFontsをセルフホストする手間のかからない方法であるgoogle-webfonts-helperの使用を検討してください。 それが不可能な場合は、ページの原点を介してGoogleFontファイルをプロキシすることができます。

    グーグルは箱から出してかなりの作業を行っているので、サーバーは遅延を避けるために少し調整する必要があるかもしれません(ありがとう、バリー!

    これは特に重要です。Chromev86(2020年10月にリリース)以降、ブラウザのキャッシュが分割されているため、フォントなどのクロスサイトリソースを同じCDNで共有できなくなりました。 この動作は、何年もの間Safariのデフォルトでした。

    しかし、それがまったく不可能な場合は、ハリー・ロバーツのスニペットを使用して、可能な限り最速のGoogleFontsにアクセスする方法があります。

    <!-- By Harry Roberts. https://csswizardry.com/2020/05/the-fastest-google-fonts/ - 1. Preemptively warm up the fonts' origin. - 2. Initiate a high-priority, asynchronous fetch for the CSS file. Works in - most modern browsers. - 3. Initiate a low-priority, asynchronous fetch that gets applied to the page - only after it's arrived. Works in all browsers with JavaScript enabled. - 4. In the unlikely event that a visitor has intentionally disabled - JavaScript, fall back to the original method. The good news is that, - although this is a render-blocking request, it can still make use of the - preconnect which makes it marginally faster than the default. --> <!-- [1] --> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <!-- [2] --> <link rel="preload" as="style" href="$CSS&display=swap" /> <!-- [3] --> <link rel="stylesheet" href="$CSS&display=swap" media="print" onload="this.media='all'" /> <!-- [4] --> <noscript> <link rel="stylesheet" href="$CSS&display=swap" /> </noscript>

    ハリーの戦略は、最初にフォントの出所を先制的にウォームアップすることです。 次に、CSSファイルの優先度の高い非同期フェッチを開始します。 その後、優先度の低い非同期フェッチを開始します。このフェッチは、ページが到着した後にのみ適用されます(印刷スタイルシートのトリックを使用)。 最後に、JavaScriptがサポートされていない場合は、元のメソッドにフォールバックします。

    ああ、Google Fontsについて話します。 &textで必要な文字だけを宣言することで、Google Fontsリクエストのサイズを最大90%削減できます。 さらに、フォント表示のサポートが最近Google Fontsにも追加されたため、そのまま使用できます。

    ただし、簡単に注意してください。 font-display: optionalを使用する場合、 preloadを使用すると、そのWebフォント要求が早期にトリガーされるため、最適ではない可能性があります(フェッチする必要のある他のクリティカルパスリソースがある場合、ネットワークの輻輳が発生します)。 クロスオリジンフォントリクエストを高速化するにはpreconnectを使用しますが、異なるオリジンwlllからフォントをpreloadするとネットワークの競合が発生するため、プリロードには注意してください。 これらのテクニックはすべて、ZachのWebフォント読み込みレシピでカバーされています。

    一方、ユーザーがユーザー補助設定で[モーションの削減]を有効にしている場合、またはデータセーバーモードを選択している場合は、Webフォント(または少なくとも第2段階のレンダリング)をオプトアウトすることをお勧めします([ Save-Data ]ヘッダーを参照)。 、またはユーザーの接続が遅い場合(Network Information API経由)。

    ユーザーがデータ保存モードを選択した場合は、 prefers-reduced-data CSSメディアクエリを使用してフォント宣言を定義しないこともできます(他のユースケースもあります)。 メディアクエリは基本的に、CSSでの使用を可能にするためにクライアントヒントHTTP拡張機能からのSave-Dataリクエストヘッダーがオン/オフであるかどうかを公開します。 現在、フラグの背後にあるChromeとEdgeでのみサポートされています。

    指標? Webフォントの読み込みパフォーマンスを測定するには、 All Text Visibleメトリック(すべてのフォントが読み込まれ、すべてのコンテンツがWebフォントで表示される瞬間)、Real Italicsまでの時間、および最初のレンダリング後のWebフォントのリフローカウントを考慮します。 明らかに、両方のメトリックが低いほど、パフォーマンスは向上します。

    可変フォントについてはどうですか? 可変フォントでは、パフォーマンスを大幅に考慮する必要がある場合があることに注意してください。 それらは活版印刷の選択のためのはるかに広いデザインスペースを私たちに与えます、しかしそれは多くの個々のファイル要求とは対照的に単一のシリアル要求の代償を伴います。

    可変フォントはフォントファイルの全体的な合計ファイルサイズを大幅に削減しますが、その単一の要求は遅く、ページ上のすべてのコンテンツのレンダリングをブロックする可能性があります。 したがって、フォントをサブセット化して文字セットに分割することは依然として重要です。 ただし、良い面としては、可変フォントを使用すると、デフォルトでリフローが1つだけ取得されるため、再描画をグループ化するためにJavaScriptは必要ありません。

    では、防弾Webフォントの読み込み戦略を立てるにはどうすればよいでしょうか。 フォントをサブセット化して2段階レンダリング用に準備し、 font-display記述子で宣言し、Font Loading APIを使用して再描画をグループ化し、永続的なServiceWorkerのキャッシュにフォントを保存します。 最初の訪問時に、ブロックする外部スクリプトの直前にスクリプトのプリロードを挿入します。 必要に応じて、BramSteinのFontFaceObserverにフォールバックできます。 また、フォント読み込みのパフォーマンスの測定に関心がある場合は、AndreasMarschkeがFontAPIとUserTimingAPIを使用したパフォーマンス追跡について説明します。

    最後に、 unicode-rangeを含めて、大きなフォントを小さな言語固有のフォントに分解し、Monica Dinculescuのfont-style-matcherを使用して、フォールバックとWebフォント。

    または、フォールバックフォントのWebフォントをエミュレートするには、@ font-face記述子を使用してフォントメトリックをオーバーライドします(デモ、Chrome 87で有効)。 (ただし、複雑なフォントスタックでは調整が複雑になることに注意してください。)

    未来は明るく見えますか? プログレッシブフォントエンリッチメントを使用すると、最終的には「任意のページでフォントの必要な部分のみをダウンロードし、その後のリクエストで、後続のページで必要に応じて元のダウンロードに追加のグリフセットを動的に「パッチ」することができるようになります。ジェイソン・パメンタルが説明しているように。 インクリメンタル転送デモはすでに利用可能であり、進行中です。

ビルドの最適化

  1. 優先順位を定義しましたか?
    最初に何を扱っているかを知っておくことをお勧めします。 すべてのアセット(JavaScript、画像、フォント、サードパーティスクリプト、およびカルーセル、複雑なインフォグラフィック、マルチメディアコンテンツなど、ページ上の「高価な」モジュール)のインベントリを実行し、それらをグループに分類します。

    スプレッドシートを設定します。 レガシーブラウザの基本的なコアエクスペリエンス(つまり、完全にアクセス可能なコアコンテンツ)、対応するブラウザの拡張エクスペリエンス(つまり、充実した完全なエクスペリエンス)、および追加機能(絶対に必要ではなく、遅延読み込みが可能なアセットなど)を定義します。 Webフォント、不要なスタイル、カルーセルスクリプト、ビデオプレーヤー、ソーシャルメディアウィジェット、大きな画像)。 数年前、このアプローチを詳細に説明した「SmashingMagazineのパフォーマンスの向上」に関する記事を公開しました。

    パフォーマンスを最適化するときは、優先順位を反映する必要があります。 コアエクスペリエンスをすぐにロードし、次に拡張機能、次に追加機能をロードします。

  2. 本番環境でネイティブJavaScriptモジュールを使用していますか?
    コアエクスペリエンスをレガシーブラウザに送信し、拡張エクスペリエンスを最新のブラウザに送信するための古き良きマスタードテクニックを覚えていますか? この手法の更新されたバリアントは、ES2017 + <script type="module">を使用できます。これは、module / nomoduleパターンとも呼ばれます(Jeremy Wagnerによって差分サービングとしても導入されています)。

    アイデアは、 2つの別々のJavaScriptバンドルをコンパイルして提供することです。「通常の」ビルド、Babel変換とポリフィルを使用して、実際にそれらを必要とするレガシーブラウザーにのみ提供するものと、変換または変換を持たない別のバンドル(同じ機能)です。ポリフィル。

    その結果、ブラウザが処理する必要のあるスクリプトの量を減らすことで、メインスレッドのブロックを減らすことができます。 Jeremy Wagnerは、ディファレンシャルサービングと、Babelのセットアップから、Webpackで行う必要のある微調整まで、ビルドパイプラインでのセットアップ方法、およびこれらすべての作業を行うことの利点に関する包括的な記事を公開しています。

    ネイティブJavaScriptモジュールスクリプトはデフォルトで延期されているため、HTML解析が行われている間、ブラウザはメインモジュールをダウンロードします。

    ネイティブJavaScriptモジュールがデフォルトでどのように延期されるかを示す例
    ネイティブJavaScriptモジュールはデフォルトで延期されます。 ネイティブJavaScriptモジュールに関するほとんどすべて。 (大プレビュー)

    ただし、警告の1つの注意: module / nomoduleパターンは一部のクライアントで逆効果になる可能性があるため、回避策を検討することをお勧めします:Jeremyのリスクの低い差動サービングパターン。ただし、プリロードスキャナーを回避し、パフォーマンスに影響を与える可能性があります。予想。 (ありがとう、ジェレミー!

    実際、Rollupは出力形式としてモジュールをサポートしているため、コードをバンドルすることも、本番環境にモジュールをデプロイすることもできます。 ParcelはParcel2でモジュールをサポートしています。Webpackの場合、module-nomodule-pluginはmodule / nomoduleスクリプトの生成を自動化します。

    :機能の検出だけでは、そのブラウザーに出荷するペイロードについて十分な情報に基づいた決定を下すのに十分ではないことを述べる価値があります。 それ自体では、ブラウザのバージョンからデバイスの機能を推測することはできません。 たとえば、発展途上国の安価なAndroidスマートフォンは、ほとんどがChromeを実行しており、メモリとCPUの機能が限られているにもかかわらず、マスタードを削減します。

    最終的には、デバイスメモリクライアントヒントヘッダーを使用して、ローエンドデバイスをより確実にターゲティングできるようになります。 執筆時点では、ヘッダーはBlinkでのみサポートされています(一般的にクライアントヒントに使用されます)。 デバイスメモリにはChromeで利用可能なJavaScriptAPIもあるため、1つのオプションは、APIに基づいて機能を検出し、サポートされていない場合はmodule / nomoduleパターンにフォールバックすることです(ありがとう、Yoav! )。

  3. ツリーシェイク、スコープホイスト、コード分割を使用していますか?
    ツリーシェーキングは、本番環境で実際に使用されるコードのみを含めてビルドプロセスをクリーンアップし、Webpackで未使用のインポートを排除する方法です。 WebpackとRollupを使用すると、コードを危険にさらすことなく、両方のツールでimportチェーンをフラット化して1つのインライン関数に変換できる場所を検出できるスコープホイストも利用できます。 Webpackでは、JSONツリーシェイクも使用できます。

    コード分​​割は、コードベースをオンデマンドでロードされる「チャンク」に分割するもう1つのWebpack機能です。 すべてのJavaScriptをすぐにダウンロード、解析、コンパイルする必要はありません。 コードで分割点を定義すると、Webpackは依存関係と出力されたファイルを処理できます。 これにより、最初のダウンロードを小さく保ち、アプリケーションから要求されたときにオンデマンドでコードを要求できます。 Alexander Kondrovが、WebpackとReactを使用したコード分割のすばらしい紹介をしています。

    コード分​​割したルートを取得し、 <link rel="preload">または<link rel="prefetch">を使用してルートをプリロードするようにブラウザに指示するpreload-webpack-pluginの使用を検討してください。 Webpackインラインディレクティブは、 preload / prefetchをある程度制御することもできます。 (ただし、優先順位の問題には注意してください。)

    分割点をどこで定義しますか? CSS / JavaScriptのどのチャンクが使用され、どのチャンクが使用されていないかを追跡する。 Umar Hansaが、Devtoolsのコードカバレッジを使用してそれを実現する方法について説明します。

    シングルページアプリケーションを扱う場合、ページをレンダリングする前にアプリを初期化するのに少し時間がかかります。 設定にはカスタムソリューションが必要ですが、初期レンダリング時間を短縮するためのモジュールとテクニックに注意することができます。 たとえば、Reactのパフォーマンスをデバッグし、一般的なReactのパフォーマンスの問題を排除する方法と、Angularのパフォーマンスを向上させる方法を次に示します。 一般に、ほとんどのパフォーマンスの問題は、アプリをブートストラップする最初の時間から発生します。

    では、積極的にコード分割するが、あまり積極的にしないための最良の方法は何でしょうか? Phil Waltonによると、「動的インポートによるコード分割に加えて、パッケージレベルでコード分割を使用することもできます。この場合、インポートされた各ノードモジュールは、パッケージの名前に基づいてチャンクに入れられます。」 Philは、それを構築する方法についてのチュートリアルも提供しています。

  4. Webpackの出力を改善できますか?
    Webpackは不思議なものと見なされることが多いため、Webpackの出力をさらに削減するのに役立つWebpackプラグインがたくさんあります。 以下は、もう少し注意が必要な、よりあいまいなもののいくつかです。

    興味深いものの1つは、IvanAkulovのスレッドからのものです。 一度呼び出した関数があり、その結果を変数に格納してから、その変数を使用しないと想像してください。 ツリーシェイクは変数を削除しますが、他の方法で使用される可能性があるため、関数は削除されませ。 ただし、この関数がどこにも使用されていない場合は、削除することをお勧めします。 これを行うには、関数呼び出しの前に/*#__PURE__*/を追加します。これは、UglifyとTerserでサポートされています—完了です。

    PURE関数の使用方法を示すエディター内のJSコードのスクリーンショット
    結果が使用されていないときにそのような関数を削除するには、関数呼び出しの前に/*#__PURE__*/を付けます。 Ivan Akulov経由(大プレビュー)

    Ivanが推奨するその他のツールのいくつかを次に示します。

    • 特にBootstrapまたはTailwindを使用している場合、purgecss-webpack-pluginは未使用のクラスを削除します。
    • 最適化を有効にしoptimization.splitChunks: 'all' withsplit-chunks-plugin。 これにより、webpackはエントリバンドルを自動的にコード分割して、キャッシュを改善します。
    • 設定optimization.runtimeChunk: true 。 これにより、webpackのランタイムが別のチャンクに移動し、キャッシュも改善されます。
    • google-fonts-webpack-pluginはフォントファイルをダウンロードするので、サーバーからそれらを提供できます。
    • workbox-webpack-pluginを使用すると、すべてのwebpackアセットの事前キャッシュ設定を使用してServiceWorkerを生成できます。 また、すぐに適用できるモジュールの包括的なガイドであるService WorkerPackagesも確認してください。 または、preload-webpack-pluginを使用して、すべてのJavaScriptチャンクのpreload / prefetchを生成します。
    • speed-measure-webpack-pluginは、webpackのビルド速度を測定し、ビルドプロセスのどのステップに最も時間がかかるかについての洞察を提供します。
    • バンドルに同じパッケージの複数のバージョンが含まれている場合、duplicate-package-checker-webpack-pluginは警告します。
    • スコープの分離を使用し、コンパイル時にCSSクラス名を動的に短縮します。

レスポンシブローダーという名前のウェブパックローダーを使用して、箱から出してレスポンシブ画像を生成する方法を示す端末のスクリーンショット
画像の速度を上げるには、小さい画面に小さい画像を表示します。 レスポンシブローダー付き。 IvanAkulov経由。 (大プレビュー)
  1. JavaScriptをWebワーカーにオフロードできますか?
    Time-to-Interactiveへの悪影響を減らすために、重いJavaScriptをWebワーカーにオフロードすることを検討することをお勧めします。

    コードベースが成長し続けると、UIパフォーマンスのボトルネックが発生し、ユーザーエクスペリエンスが低下します。 これは、DOM操作がメインスレッドでJavaScriptと並行して実行されているためです。 Webワーカーを使用すると、これらの高価な操作を、別のスレッドで実行されているバックグラウンドプロセスに移動できます。 Webワーカーの一般的な使用例は、データのプリフェッチとプログレッシブWebアプリで、必要なときに後で使用できるように、事前にデータを読み込んで保存します。 また、Comlinkを使用して、メインページとワーカー間の通信を合理化できます。 まだやるべきことがいくつかありますが、私たちはそこに到達しています。

    フレームワークとアプリロジックをWebワーカーに移動するさまざまなアプローチを示す、Webワーカーに関する興味深いケーススタディがいくつかあります。 結論:一般的に、まだいくつかの課題がありますが、すでにいくつかの良いユースケースがあります(ありがとう、Ivan Akulov! )。

    Chrome 80から、JavaScriptモジュールのパフォーマンス上の利点を備えたWebワーカー用の新しいモードが出荷されました。これはモジュールワーカーと呼ばれます。 スクリプトの読み込みと実行をscript type="module"に一致するように変更できます。さらに、ワーカーの実行をブロックせずに、遅延読み込みコードに動的インポートを使用することもできます。

    どうやって始めるのか? 調べる価値のあるいくつかのリソースを次に示します。

    • Surmaは、ブラウザーのメインスレッドからJavaScriptを実行する方法と、Webワーカーをいつ使用する必要があるかについての優れたガイドを公開しています。
    • また、メインスレッドアーキテクチャから離れたSurmaの話を確認してください。
    • ShubhiePanickerとJasonMillerによる応答性を保証するためのクエストは、Webワーカーの使用方法と、それらを回避するタイミングについての詳細な洞察を提供します。
    • ユーザーの邪魔にならないようにする:Webワーカーのジャンクを減らすWebワーカーを操作するための便利なパターン、ワーカー間の通信、メインスレッドからの複雑なデータ処理の処理、テストとデバッグの効果的な方法を紹介します。
    • Workerizeを使用すると、モジュールをWebワーカーに移動して、エクスポートされた関数を非同期プロキシとして自動的に反映できます。
    • Webpackを使用している場合は、workerize-loaderを使用できます。 または、worker-pluginを使用することもできます。
    Webワーカーを使用するときに使用するものと避けるべきものの例として左側に示されているDOMのコード
    コードが長時間ブロックされる場合はWebワーカーを使用しますが、DOMに依存し、入力応答を処理し、遅延を最小限に抑える必要がある場合は、Webワーカーを使用しないでください。 (Addy Osmani経由)(大プレビュー)

    DOMは「スレッドセーフ」ではないため、WebワーカーはDOMにアクセスできず、実行するコードは別のファイルに含める必要があることに注意してください。

  2. 「ホットパス」をWebAssemblyにオフロードできますか?
    計算量の多いタスクをWebAssembly( WASM )にオフロードできます。これは、C / C ++ / Rustなどの高級言語をコンパイルするためのポータブルターゲットとして設計されたバイナリ命令フォーマットです。 そのブラウザのサポートは注目に値し、JavaScriptとWASM間の関数呼び出しが高速化するにつれて、最近実行可能になりました。 さらに、Fastlyのエッジクラウドでもサポートされています。

    もちろん、WebAssemblyはJavaScriptに取って代わるものではありませんが、CPUの占有に気付いた場合にJavaScriptを補完することができます。 ほとんどのWebアプリでは、JavaScriptの方が適しています。また、WebAssemblyは、ゲームなどの計算量の多いWebアプリに最適です。

    WebAssemblyについて詳しく知りたい場合は、次のようにします。

    • Lin ClarkはWebAssemblyに徹底的なシリーズを書き、Milica Mihajlijaは、ブラウザーでネイティブコードを実行する方法、それを実行する理由、JavaScriptとWeb開発の将来にとってそれが何を意味するかについての一般的な概要を説明します。
    • WebAssemblyを使用してWebアプリを20倍高速化する方法(ケーススタディ)では、JavaScriptの計算がコンパイルされたWebAssemblyに置き換えられ、パフォーマンスが大幅に向上したケーススタディを紹介しています。
    • Patrick Hamannは、WebAssemblyの役割の拡大について語っています。彼は、WebAssemblyに関するいくつかの神話を暴き、その課題を探り、今日のアプリケーションで実際に使用できるようにしています。
    • Google Codelabsは、WebAssemblyの概要を提供します。このコースでは、ネイティブコードをCで取得し、WebAssemblyにコンパイルして、JavaScriptから直接呼び出す方法を学習します。
    • Alex Daniloは、WebAssemblyと、それがGoogle I / Oトークでどのように機能するかを説明しました。 また、Benedek Gagyiは、WebAssemblyに関する実用的なケーススタディ、具体的には、チームがiOS、Android、およびWebサイトへのC ++コードベースの出力形式としてWebAssemblyをどのように使用するかを共有しました。

    GPUにアクセスするためにWebワーカー、Webアセンブリ、ストリーム、またはおそらくWebGL JavaScript APIをいつ使用するかについてまだわかりませんか? JavaScriptの高速化は、何をいつ使用するのか、そしてその理由を説明する短いが役立つガイドです。また、便利なフローチャートと豊富な有用なリソースが含まれています。

左側に示されているC ++、C、またはRustの図で、JavaScript、CSS、およびHTMLに追加されたWASMバイナリを含むブラウザーを示す矢印が付いています。
Milica Mihajlijaが、WebAssemblyの仕組みとその有用性の概要を説明します。 (大プレビュー)
  1. レガシーコードをレガシーブラウザにのみ提供しますか?
    ES2017は最新のブラウザーで非常によくサポートされているため、 babelEsmPluginを使用して、対象の最新のブラウザーでサポートされていないES2017 +機能のみをトランスパイルできます。

    HousseinDjirdehとJasonMillerは最近、最新およびレガシーのJavaScriptをトランスパイルして提供する方法、WebpackとRollupで動作させる方法、および必要なツールに関する包括的なガイドを公開しました。 また、サイトまたはアプリバンドルで削減できるJavaScriptの量を見積もることもできます。

    JavaScriptモジュールはすべての主要なブラウザでサポートされているため、 script type="module"を使用して、ESモジュールをサポートするブラウザがファイルをロードできるようにします。古いブラウザはscript nomoduleを使用してレガシービルドをロードできます。

    最近では、トランスパイラーやバンドラーを使用せずに、ブラウザーでネイティブに実行されるモジュールベースのJavaScriptを作成できます。 <link rel="modulepreload">ヘッダーは、モジュールスクリプトの早期(および優先度の高い)ロードを開始する方法を提供します。 基本的に、これは帯域幅の使用量を最大化するのに役立つ便利な方法です。ブラウザにフェッチする必要があるものを通知して、長いラウンドトリップ中に何もする必要がないようにします。 また、Jake Archibaldは、ESモジュールで覚えておくべき落とし穴や注意事項を含む詳細な記事を公開しています。これは読む価値があります。

インラインスクリプトは、外部スクリプトをブロックしてインラインスクリプトが実行されるまで延期されます
Jake Archibaldは、ESモジュールで注意すべき点と注意事項を含む詳細な記事を公開しました。たとえば、インラインスクリプトは、外部スクリプトとインラインスクリプトが実行されるまで延期されます。 (大プレビュー)
  1. インクリメンタルデカップリングを使用してレガシーコードを特定して書き直します
    長期にわたるプロジェクトは、ほこりや古いコードを収集する傾向があります。 依存関係を再検討し、最近問題を引き起こしているレガシーコードをリファクタリングまたはリライトするために必要な時間を評価します。 もちろん、それは常に大きな仕事ですが、レガシーコードの影響を理解したら、インクリメンタルデカップリングから始めることができます。

    まず、レガシーコード呼び出しの比率が一定のままであるか、上昇ではなく下降しているかを追跡するメトリックを設定します。 チームがライブラリを使用することを公に阻止し、ライブラリがプルリクエストで使用されている場合はCIが開発者に警告するようにします。 ポリフィルは、レガシーコードから標準のブラウザ機能を使用する書き直されたコードベースへの移行に役立つ可能性があります。

  2. 未使用のCSS / JSを特定して削除します。
    ChromeのCSSおよびJavaScriptコードカバレッジにより、実行/適用されたコードと実行されていないコードを知ることができます。 カバレッジの記録を開始し、ページでアクションを実行してから、コードカバレッジの結果を調べることができます。 未使用のコードを検出したら、 import()を使用してそれらのモジュールと遅延読み込みを見つけます(スレッド全体を参照)。 次に、カバレッジプロファイルを繰り返し、初期ロードで出荷されるコードが少なくなっていることを確認します。

    Puppeteerを使用して、プログラムでコードカバレッジを収集できます。 Chromeでは、コードカバレッジの結果をエクスポートすることもできます。 Andy Daviesが指摘したように、最新のブラウザと従来のブラウザの両方のコードカバレッジを収集することをお勧めします。

    もう少し露出が必要なPuppetterのユースケースとツールは他にもたくさんあります。

    • Puppeteerのユースケース。たとえば、自動視覚的差分や、ビルドごとの未使用のCSSの監視など。
    • Puppeteerを使用したWebパフォーマンスレシピ、
    • PupeeteerおよびPlaywrightスクリプトを記録および生成するための便利なツール、
    • さらに、DevToolsでテストを直接記録することもできます。
    • Nitay NeemanによるPuppeteerの包括的な概要と、例と使用例。
    左側にPupeteerRecorderのスクリーンショット、右側にPuppeteerSandboxのスクリーンショットを示します。
    PuppeteerRecorderとPuppeteerSandboxを使用して、ブラウザーの操作を記録し、PuppeteerとPlaywrightのスクリプトを生成できます。 (大プレビュー)

    さらに、purgecss、UnCSS、およびHeliumは、CSSから未使用のスタイルを削除するのに役立ちます。 また、疑わしいコードがどこかで使用されているかどうかわからない場合は、ハリーロバーツのアドバイスに従うことができます。特定のクラス用に1×1pxの透明なGIFを作成し、それをdead/ディレクトリ(例: /assets/img/dead/comments.gif )にドロップします。 /assets/img/dead/comments.gif

    その後、その特定の画像をCSSの対応するセレクターの背景として設定し、ファイルがログに表示される場合は、数か月待ってください。 エントリがない場合、そのレガシーコンポーネントが画面に表示されることはありません。おそらく、先に進んですべてを削除することができます。

    I-feel-adventurous -departmentの場合、DevToolsを使用してDevToolsを監視することにより、一連のページから未使用のCSSの収集を自動化することもできます。

Webpack比較表
彼の記事で、Benedikt Rotschは、Moment.jsからdate-fnsに切り替えると、3Gおよびローエンドの携帯電話のFirstpaintで約300ms短縮できることを示しました。 (大プレビュー)
  1. JavaScriptバンドルのサイズをトリミングします。
    Addy Osmaniが指摘したように、必要なのがほんの一部である場合に完全なJavaScriptライブラリを出荷する可能性が高く、それらを必要としないブラウザ用の古いポリフィル、または単にコードを複製するだけです。 オーバーヘッドを回避するには、ビルドプロセス中に未使用のメソッドとポリフィルを削除するwebpack-libs-optimizationsの使用を検討してください。

    従来のブラウザーと最新のブラウザーに送信しているポリフィルを確認して確認し、それらについてより戦略的にします。 polyfill.ioを見てください。これは、一連のブラウザー機能の要求を受け入れ、要求しているブラウザーに必要なポリフィルのみを返すサービスです。

    バンドル監査を通常のワークフローにも追加します。 数年前に追加した重いライブラリに代わる軽量の代替手段があるかもしれません。たとえば、Moment.js(現在は廃止されています)を次のように置き換えることができます。

    • ネイティブ国際化API、
    • おなじみのMoment.jsAPIとパターンを備えたDay.js、
    • date-fnsまたは
    • ルクソン。
    • 人間がレビューしたパッケージの推奨事項と品質重視の検索を組み合わせたSkypackDiscoverを使用することもできます。

    Benedikt Rotschの調査によると、Moment.jsからdate-fnsに切り替えると、3Gおよびローエンドの携帯電話のFirstpaintで約300ミリ秒短縮できることがわかりました。

    バンドル監査の場合、Bundlephobiaはnpmパッケージをバンドルに追加するコストを見つけるのに役立ちます。 size-limitは、JavaScriptの実行時間の詳細を使用して、基本的なバンドルサイズチェックを拡張します。 これらのコストをLighthouseCustomAuditと統合することもできます。 これはフレームワークにも当てはまります。 Vue MDCアダプター(Vueのマテリアルコンポーネント)を削除またはトリミングすることにより、スタイルは194KBから10KBに低下します。

    依存関係と実行可能な代替案の影響について情報に基づいた決定を下すのに役立つ、さらに多くのツールがあります。

    • webpack-bundle-analyzer
    • ソースマップエクスプローラー
    • バンドルバディ
    • バンドル恐怖症
    • Webpackの分析は、特定のモジュールがバンドルに含まれている理由を示しています。
    • bundle-wizardは、ページ全体の依存関係のマップも作成します。
    • Webpackサイズ-プラグイン
    • VisualCodeのインポートコスト

    フレームワーク全体を出荷する代わりに、フレームワークをトリミングして、追加のコードを必要としない生のJavaScriptバンドルにコンパイルすることもできます。 Svelteはそれを実行し、ビルド時にReact.jsコンポーネントをネイティブDOM操作に変換するRawactBabelプラグインも実行します。 なんで? メンテナが説明するように、「react-domには、インクリメンタルレンダリング、スケジューリング、イベント処理などのコードを含む、レンダリング可能なすべてのコンポーネント/ HTMLElementのコードが含まれています。ただし、これらすべての機能を必要としないアプリケーションがあります(最初はページの読み込み)。このようなアプリケーションの場合、ネイティブDOM操作を使用してインタラクティブなユーザーインターフェイスを構築するのが理にかなっている場合があります。」

size-limitは、JavaScriptの実行時間の詳細を含む基本的なバンドルサイズチェックを提供します
size-limitは、JavaScriptの実行時間の詳細を含む基本的なバンドルサイズチェックを提供します。 (大プレビュー)
  1. 部分的な水分補給を使用しますか?
    アプリケーションで使用されるJavaScriptの量を考えると、クライアントへの送信をできるだけ少なくする方法を見つける必要があります。 そのための1つの方法は、部分的な水和を使用することです。 考え方は非常に単純です。SSRを実行してからアプリ全体をクライアントに送信する代わりに、アプリのJavaScriptのごく一部だけをクライアントに送信してからハイドレイトします。 それは、静的なWebサイト上に複数のレンダリングルートを持つ複数の小さなReactアプリと考えることができます。

    「部分的な水分補給の場合(NextとPreactを使用)」の記事で、Lukas Bombachは、ドイツの報道機関の1つであるWelt.deの背後にあるチームが部分的な水分補給でより良いパフォーマンスを達成した方法を説明しています。 説明とコードスニペットを使用して、次の超高性能GitHubリポジトリを確認することもできます。

    別のオプションを検討することもできます。

    • Preactと11による部分的な水分補給、
    • React GitHubリポジトリでのプログレッシブハイドレーション、
    • Vue.js(GitHubリポジトリ)での怠惰な水分補給、
    • インタラクションパターンをインポートして、ユーザーがそれを必要とするUIとインタラクションするときに、重要ではないリソース(コンポーネント、埋め込みなど)を遅延ロードします。

    Jason Millerは、Reactを使用してプログレッシブハイドレーションを実装する方法に関する実用的なデモを公開しているため、すぐに使用できます:デモ1、デモ2、デモ3(GitHubでも入手可能)。 さらに、react-prerendered-componentライブラリを調べることができます。

    Googleドキュメントのloadshare()で+ 485KBのJavaScript
    ファーストパーティコードのインポートオンインタラクションは、インタラクションの前にリソースをプリフェッチできない場合にのみ実行する必要があります。 (大プレビュー)
  2. React / SPAの戦略を最適化しましたか?
    シングルページアプリケーションアプリケーションのパフォーマンスに苦労していますか? Jeremy Wagnerは、クライアント側のフレームワークのパフォーマンスがさまざまなデバイスに与える影響を調査し、使用するときに知っておく必要のある影響とガイドラインのいくつかを強調しました。

    その結果、JeremyがReactフレームワークに使用することを提案しているSPA戦略は次のとおりです(ただし、他のフレームワークでは大幅に変更されるべきではありません)。

    • 可能な限り、ステートフルコンポーネントをステートレスコンポーネントとしてリファクタリングします。
    • サーバーの応答時間を最小限に抑えるために、可能な場合はステートレスコンポーネントを事前レンダリングします。 サーバー上でのみレンダリングします。
    • 単純な対話性を持つステートフルコンポーネントの場合、そのコンポーネントを事前レンダリングまたはサーバーレンダリングすることを検討し、その対話性をフレームワークに依存しないイベントリスナーに置き換えます。
    • クライアントでステートフルコンポーネントをハイドレイトする必要がある場合は、可視性または相互作用にレイジーハイドレーションを使用します。
    • 遅延水和コンポーネントの場合、 requestIdleCallbackを使用して、メインスレッドのアイドル時間中に水和をスケジュールします。

    あなたが追求またはレビューしたいと思うかもしれない他のいくつかの戦略があります:

    • ReactアプリでのCSS-in-JSのパフォーマンスに関する考慮事項
    • 動的インポートと遅延ハイドレーションを使用して、必要な場合にのみポリフィルをロードすることにより、Next.jsバンドルサイズを減らします。
    • JavaScriptの秘密:React、パフォーマンスの最適化、マルチスレッドの物語、Reactによるユーザーインターフェイスの課題の改善に関する7部構成の長いシリーズ、
    • Reactのパフォーマンスを測定する方法とReactアプリケーションをプロファイリングする方法。
    • ReactでモバイルファーストのWebアニメーションを構築します。これは、Alex Holachekによる素晴らしい講演であり、スライドとGitHubリポジトリも含まれています(ヒントをありがとう、Addy! )。
    • webpack-libs-optimizationsは、Webpack固有のパフォーマンス関連の最適化が豊富に用意された素晴らしいGitHubリポジトリです。 IvanAkulovによって維持されています。
    • NotionでのReactパフォーマンスの向上、Reactでのパフォーマンスを向上させる方法に関するIvan Akulovによるガイド、アプリを約30%高速化するための便利なポインターがたくさんあります。
    • React Refresh Webpackプラグイン(実験的)は、コンポーネントの状態を保持し、フックと関数コンポーネントをサポートするホットリロードを可能にします。
    • バンドルサイズに影響を与えない、新しく提案された種類のコンポーネントである、バンドルサイズがゼロのReactサーバーコンポーネントに注意してください。 プロジェクトは現在開発中ですが、コミュニティからのフィードバックは大歓迎です(ソフィーアルパートによる素晴らしい説明者)。
  3. JavaScriptチャンクに予測プリフェッチを使用していますか?
    ヒューリスティックを使用して、JavaScriptチャンクをプリロードするタイミングを決定できます。 Guess.jsは、Google Analyticsデータを使用して、ユーザーが特定のページから次にアクセスする可能性が最も高いページを判別するツールとライブラリのセットです。 Guess.jsは、Google Analyticsまたはその他のソースから収集されたユーザーナビゲーションパターンに基づいて、後続の各ページで必要となるJavaScriptを予測およびプリフェッチするための機械学習モデルを構築します。

    したがって、すべてのインタラクティブ要素はエンゲージメントの確率スコアを受け取り、そのスコアに基づいて、クライアント側のスクリプトは事前にリソースをプリフェッチすることを決定します。 この手法をNext.jsアプリケーションであるAngularとReactに統合できます。また、セットアッププロセスを自動化するWebpackプラグインもあります。

    明らかに、不要なデータを消費して望ましくないページをプリフェッチするようにブラウザに促す可能性があるため、プリフェッチされるリクエストの数をかなり控えめにすることをお勧めします。 良い使用例は、チェックアウトに必要な検証スクリプトのプリフェッチ、または重要な召喚状がビューポートに入ったときの投機的なプリフェッチです。

    より洗練されていないものが必要ですか? DNStradamusは、ビューポートに表示されるアウトバウンドリンクのDNSプリフェッチを実行します。 Quicklink、InstantClick、Instant.pageは、次のページのナビゲーションの読み込みを高速化するために、アイドル時にビューポートのリンクを自動的にプリフェッチする小さなライブラリです。 クイックリンクを使用すると、ReactルーターのルートとJavascriptをプリフェッチできます。 さらに、データを考慮しているため、2Gでプリフェッチしたり、 Data-Saverがオンになっている場合はプリフェッチしません。 モードがビューポートプリフェッチ(デフォルト)を使用するように設定されている場合、Instant.pageも同様です。

    予測プリフェッチの科学を詳細に調べたい場合は、Divya Tagtachianが、The Art of Predictive Prefetchについて、最初から最後まですべてのオプションをカバーする素晴らしい講演を行っています。

  4. ターゲットJavaScriptエンジンの最適化を利用します。
    ユーザーベースでJavaScriptエンジンが支配的であるものを調べてから、それらを最適化する方法を探ります。 たとえば、Blink-browsers、Node.jsランタイム、Electronで使用されるV8を最適化する場合は、モノリシックスクリプトのスクリプトストリーミングを利用します。

    スクリプトストリーミングを使用すると、ダウンロードが開始されると、 asyncまたはdefer scriptsを別のバックグラウンドスレッドで解析できるため、場合によっては、ページの読み込み時間が最大10%向上します。 実際には、 <head><script defer>を使用して、ブラウザがリソースを早期に検出し、バックグラウンドスレッドで解析できるようにします。

    警告Opera Miniはスクリプトの延期をサポートしていないため、インドまたはアフリカ向けに開発している場合、 deferは無視され、スクリプトが評価されるまでレンダリングがブロックされます(Jeremyに感謝します)

    また、V8のコードキャッシングにフックすることもできます。ライブラリをコードから分割するか、またはその逆で、ライブラリとその使用法を1つのスクリプトにマージし、小さなファイルをグループ化して、インラインスクリプトを回避します。 または、v8-compile-cacheを使用することもできます。

    JavaScript全般に関しては、覚えておく価値のあるいくつかのプラクティスもあります。

    • JavaScriptのクリーンコードの概念、読み取り可能、再利用可能、およびリファクタリング可能なコードを記述するためのパターンの大規模なコレクション。
    • データをアップロードする前にgzipに圧縮するなど、CompressionStream APIを使用してJavaScriptからデータを圧縮できます(Chrome80以降)。
    • 分離されたウィンドウのメモリリークとWebアプリのメモリリークの修正は、トリッキーなJavaScriptメモリリークを見つけて修正する方法に関する詳細なガイドです。 さらに、DevToolsコンソールからqueryObjects(SomeConstructor)を使用できます(ありがとう、Mathias! )。
    • 再エクスポートは、読み込みと実行時のパフォーマンスに悪影響を及ぼします。再エクスポートを回避すると、バンドルサイズを大幅に削減できます。
    • optionsパラメータにフラグを設定することで、パッシブイベントリスナーのスクロールパフォーマンスを向上させることができます。 そのため、ブラウザは、リスナーが終了した後ではなく、すぐにページをスクロールできます。 (Kayce Basques経由)。
    • scrollまたはtouch*リスナーがある場合は、 passive: trueをaddEventListenerに渡します。 これにより、内部でevent.preventDefault()を呼び出す予定がないことがブラウザに通知されるため、これらのイベントの処理方法を最適化できます。 (Ivan Akulov経由)
    • isInputPending()を使用すると、JavaScriptのスケジューリングを改善できます。これは、Web上のユーザー入力の割り込みの概念を使用して、読み込みと応答性の間のギャップを埋めようとする新しいAPIであり、JavaScriptがブラウザ。
    • 実行後にイベントリスナーを自動的に削除することもできます。
    • Firefoxの最近リリースされたWarp、SpiderMonkeyの重要なアップデート(Firefox 83で出荷)、Baseline Interpreter、およびいくつかのJIT最適化戦略も利用できます。
時間の読み込みと応答性を理解するのに役立つイラスト
実行中のJSを示す青いバナーで、通常のギャップに白い線が表示されます。これは、ブラウザに実行を譲るオーバーヘッドを発生させることなく、ユーザー入力があるかどうかを事前に確認する時間を表します。
isInputPending()は、読み込みと応答性の間のギャップを埋めようとする新しいブラウザーAPIです。(大プレビュー)
さまざまなドメイン、サードパーティのスクリプトに至るまでの各リクエストのチェーンを示すマップの図
CNN.comのリクエストマップは、さまざまなドメインへの各リクエストのチェーンを、サードパーティのスクリプトに至るまで示しています。 ソース。 (大プレビュー)
  1. 常にサードパーティのアセットをセルフホストすることを好みます。
    繰り返しになりますが、デフォルトでは静的アセットをセルフホストします。 多くのサイトが同じパブリックCDNと同じバージョンのJavaScriptライブラリまたはWebフォントを使用している場合、訪問者はブラウザにすでにキャッシュされているスクリプトとフォントを使用してサイトにアクセスし、エクスペリエンスを大幅に高速化すると想定するのが一般的です。 。 ただし、発生する可能性はほとんどありません。

    セキュリティ上の理由から、フィンガープリントを回避するために、ブラウザは2013年にSafariで、昨年はChromeで導入されたパーティションキャッシュを実装しています。 したがって、2つのサイトがまったく同じサードパーティのリソースURLを指している場合、コードはドメインごとに1回ダウンロードされ、プライバシーへの影響により、キャッシュはそのドメインに「サンドボックス化」されます( David Calhounに感謝します)。 したがって、パブリックCDNを使用しても、パフォーマンスが自動的に向上するわけではありません。

    さらに、リソースは予想される限りブラウザのキャッシュに存在せず、サードパーティのアセットよりもファーストパーティのアセットがキャッシュに留まる可能性が高いことに注意してください。 したがって、セルフホスティングは通常、より信頼性が高く安全であり、パフォーマンスにも優れています。

  2. サードパーティのスクリプトの影響を抑制します。
    すべてのパフォーマンスの最適化が実施されていると、ビジネス要件に由来するサードパーティのスクリプトを制御できないことがよくあります。 サードパーティスクリプトのメトリックはエンドユーザーエクスペリエンスの影響を受けないため、1つのスクリプトが不快なサードパーティスクリプトのロングテールを呼び出すことが多く、専用のパフォーマンスの取り組みが台無しになります。 これらのスクリプトがもたらすパフォーマンスの低下を抑えて軽減するには、スクリプトの読み込みと実行を延期し、リソースヒント( dns-prefetchまたはpreconnect )を介して接続をウォームアップするだけでは不十分です。

    現在、すべてのJavaScriptコード実行時間の57%がサードパーティのコードに費やされています。 モバイルサイトの中央値は12のサードパーティドメインにアクセスし、中央値は37の異なるリクエスト(または各サードパーティに対して行われた約3つのリクエスト)です。

    さらに、これらのサードパーティは、多くの場合、サードパーティのスクリプトを招待して参加するため、パフォーマンスの大きなボトルネックになり、ページ上の8番目のパーティのスクリプトにまで及ぶこともあります。 したがって、依存関係とタグマネージャーを定期的に監査すると、コストのかかる驚きがもたらされる可能性があります。

    Yoav Weissがサードパーティのスクリプトに関する講演で説明したように、もう1つの問題は、多くの場合、これらのスクリプトが動的なリソースをダウンロードすることです。 リソースはページの読み込みごとに変化するため、リソースがダウンロードされるホストとリソースがどのホストになるかは必ずしもわかりません。

    上記のように、延期はほんの始まりに過ぎないかもしれませんが、サードパーティのスクリプトもアプリから帯域幅とCPU時間を盗むためです。 もう少し積極的に、アプリが初期化されたときにのみロードすることができます。

    /* Before */ const App = () => { return <div> <script> window.dataLayer = window.dataLayer || []; function gtag(){...} gtg('js', new Date()); </script> </div> } /* After */ const App = () => { const[isRendered, setRendered] = useState(false); useEffect(() => setRendered(true)); return <div> {isRendered ? <script> window.dataLayer = window.dataLayer || []; function gtag(){...} gtg('js', new Date()); </script> : null} </div> }

    「サードパーティタグのサイト速度への影響の削減」に関する素晴らしい投稿で、Andy Daviesは、コストの特定から影響の削減まで、サードパーティのフットプリントを最小限に抑える戦略を探っています。

    Andyによると、タグがサイトの速度に影響を与える2つの方法があります。訪問者のデバイスでのネットワーク帯域幅と処理時間の競合であり、実装方法によっては、HTMLの解析も遅らせる可能性があります。 したがって、最初のステップは、WebPageTestを使用してスクリプトを使用して、または使用せずにサイトテストすることにより、サードパーティが与える影響を特定することです。 Simon Hearneのリクエストマップを使用すると、サードパーティのサイズ、タイプ、およびロードのトリガーの詳細とともに、サードパーティをページ上に視覚化することもできます。

    できればセルフホストして単一のホスト名を使用しますが、リクエストマップを使用して、サードパーティの呼び出しを公開し、スクリプトが変更されたことを検出します。 ハリー・ロバーツのアプローチを使用してサードパーティを監査し、このようなスプレッドシートを作成できます(ハリーの監査ワークフローも確認してください)。

    その後、既存のスクリプトの軽量な代替案を検討し、重複や主な原因をより軽いオプションにゆっくりと置き換えることができます。 おそらく、一部のスクリプトは、完全なタグではなく、フォールバックトラッキングピクセルに置き換えることができます。

    左の例はlite-youtubeカスタム要素を使用した3KBのJavaScriptを示し、中央と右の例はlite-youtubeカスタム要素を使用した+ 540KBのJavaScriptを示しています
    YouTubeにファサードをロードします。たとえば、実際のYouTubeプレーヤーよりも大幅に小さいlite-youtube-embedです。 (画像ソース)(大きなプレビュー)

    実行可能でない場合は、少なくともサードパーティのリソースをファサードで遅延ロードできます。つまり、実際の埋め込みサードパーティに似ている静的要素ですが、機能しないため、ページの読み込みにかかる負担がはるかに少なくなります。 したがって、トリックは、インタラクションでのみ実際の埋め込みをロードすることです。

    たとえば、次を使用できます。

    • lite-vimeo-Vimeoプレーヤー用に埋め込み、
    • lite-Vimeoプレーヤー用のvimeo、
    • lite-youtube-YouTubeプレーヤー用に埋め込み、
    • ライブチャット用のreact-live-chat-loader(ケーススタディ、および別のケーススタディ)、
    • iframeのlazyframe。

    タグマネージャーのサイズが通常大きい理由の1つは、同時に実行される多数の実験と、多くのユーザーセグメント、ページURL、サイトなどが原因です。したがって、Andyによると、それらを減らすと両方を減らすことができます。ダウンロードサイズとブラウザでスクリプトを実行するのにかかる時間。

    そして、アンチフリッカースニペットがあります。 グーグルオプティマイズ、ビジュアルウェブオプティマイザー(VWO)などのサードパーティは、それらを使用する際に全会一致です。 これらのスニペットは通常、 A / Bテストの実行とともに挿入されます。異なるテストシナリオ間のちらつきを避けるために、 opacity: 0でドキュメントのbodyを非表示にし、数秒後に呼び出されてopacityを元に戻す関数を追加します。 。 これにより、クライアント側の実行コストが大幅に高くなるため、レンダリングが大幅に遅延することがよくあります。

    訪問者がナビゲーションを開始したときに、コンテンツがちらつき防止スニペットによって隠される方法とタイミングを示す、0.0秒から6.0秒までの7つのプレビュー
    A / Bテストを使用すると、顧客はこのようなちらつきをよく目にします。 アンチフリッカースニペットはそれを防ぎますが、パフォーマンスにもコストがかかります。 アンディデイビス経由。 (大プレビュー)

    したがって、ちらつき防止タイムアウトがトリガーされる頻度を追跡し、タイムアウトを減らします。 デフォルトでは、ページの表示が最大4秒ブロックされるため、コンバージョン率が低下します。 Tim Kadlecによると、「友人は友人にクライアント側のA / Bテストを行わせない」とのことです。 CDNでのサーバー側のA / Bテスト(エッジコンピューティングやエッジスライスレンダリングなど)は、常にパフォーマンスの高いオプションです。

    全能のGoogleタグマネージャーに対処する必要がある場合、バリーポラードはGoogleタグマネージャーの影響を封じ込めるためのいくつかのガイドラインを提供します。 また、Christian Schaeferは、広告を読み込むための戦略を検討しています。

    注意:サードパーティのウィジェットの中には、監査ツールから身を隠すものがあるため、見つけて測定するのがより難しい場合があります。 サードパーティのストレステストを行うには、DevToolsのパフォーマンスプロファイルページでボトムアップの概要を調べ、リクエストがブロックされた場合やタイムアウトした場合にどうなるかをテストします。後者の場合は、WebPageTestのBlackholeサーバーblackhole.webpagetest.orgを使用できます。 hostsファイル内の特定のドメインを指すことができます。

    では、どのような選択肢がありますか? タイムアウトを使用してリソースのダウンロードを競合させてサービスワーカーを使用することを検討してください。リソースが特定のタイムアウト内に応答しなかった場合は、空の応答を返して、ページの解析を続行するようにブラウザーに指示してください。 成功しなかった、または特定の基準を満たさないサードパーティのリクエストをログに記録またはブロックすることもできます。 可能であれば、ベンダーのサーバーからではなく、独自のサーバーからサードパーティのスクリプトを読み込み、遅延読み込みします。

    もう1つのオプションは、コンテンツセキュリティポリシー(CSP)を確立して、サードパーティのスクリプトの影響を制限することです。たとえば、オーディオやビデオのダウンロードを禁止します。 最善のオプションは、 <iframe>を介してスクリプトを埋め込むことです。これにより、スクリプトはiframeのコンテキストで実行され、ページのDOMにアクセスできなくなり、ドメインで任意のコードを実行できなくなります。 sandbox属性を使用してIframeをさらに制限できるため、スクリプトの実行の防止、アラートの防止、フォームの送信、プラグイン、トップナビゲーションへのアクセスなど、iframeが実行する可能性のある機能を無効にすることができます。

    また、機能ポリシーを使用したブラウザ内パフォーマンスリンティングを介して、サードパーティをチェックすることもできます。これは、比較的新しい機能であり、 サイトの特定のブラウザ機能をオプトインまたはオプトアウトします。 (補足として、サイズが大きく最適化されていない画像、サイズが正しくないメディア、同期スクリプトなどを回避するためにも使用できます)。 現在、Blinkベースのブラウザでサポートされています。

    /* Via Tim Kadlec. https://timkadlec.com/remembers/2020-02-20-in-browser-performance-linting-with-feature-policies/ */ /* Block the use of the Geolocation API with a Feature-Policy header. */ Feature-Policy: geolocation 'none'
    /* Via Tim Kadlec. https://timkadlec.com/remembers/2020-02-20-in-browser-performance-linting-with-feature-policies/ */ /* Block the use of the Geolocation API with a Feature-Policy header. */ Feature-Policy: geolocation 'none'

    多くのサードパーティスクリプトがiframeで実行されているため、それらの許容量を徹底的に制限する必要があります。 サンドボックス化されたiframeは常に良いアイデアであり、 sandbox属性のいくつかのallow値を使用して、それぞれの制限を解除できます。 サンドボックス化はほとんどすべての場所でサポートされているため、サードパーティのスクリプトを、許可されるべき最小限のスクリプトに制限します。

    エンティティのスクリプトの平均実行にかかる時間を視覚化したThirdPartyWeb.TodayWebサイトのスクリーンショット
    ThirdPartyWeb.Todayは、すべてのサードパーティスクリプトをカテゴリ(分析、ソーシャル、広告、ホスティング、タグマネージャーなど)でグループ化し、エンティティのスクリプトの実行にかかる時間(平均)を視覚化します。 (大プレビュー)

    交差点オブザーバーの使用を検討してください。 これにより、イベントをディスパッチしたり、DOMから必要な情報(広告の可視性など)を取得したりしながら、広告をiframedすることができます。 機能ポリシー、リソースサイズの制限、CPU /帯域幅の優先度などの新しいポリシーに注意して、同期スクリプト、同期XHRリクエスト、 document.write 、古い実装など、ブラウザの速度を低下させる有害なWeb機能やスクリプトを制限します。

    最後に、サードパーティのサービスを選択するときは、Patrick HulceのThirdPartyWeb.Todayを確認することを検討してください。これは、すべてのサードパーティのスクリプトをカテゴリ(分析、ソーシャル、広告、ホスティング、タグマネージャーなど)ごとにグループ化し、エンティティのスクリプトの長さを視覚化するサービスです。実行するために取る(平均して)。 明らかに、最大のエンティティは、それらが表示されているページに最も悪いパフォーマンスの影響を与えます。 ページをざっと読むだけで、期待するパフォーマンスフットプリントがわかります。

    ああ、そして通常の容疑者を忘れないでください。共有用のサードパーティウィジェットの代わりに、静的なソーシャル共有ボタン(SSBGなど)とインタラクティブマップの代わりにインタラクティブマップへの静的リンクを使用できます。

ファーストパーティとサードパーティのリクエストの割合を比較したグラフの例:399KBはファーストパーティのリクエストの27%に相当し、1.15MBはサードパーティのリクエストの73%に相当します
Casper.comは、Optimizelyをセルフホスティングすることでサイトから1.7秒短縮する方法に関する詳細なケーススタディを公開しました。 それは価値があるかもしれません。 (画像ソース)(大きなプレビュー)
  1. HTTPキャッシュヘッダーを適切に設定します。
    キャッシングは非常に明白なことのようですが、正しく行うのはかなり難しいかもしれません。 expiresmax-agecache-control 、およびその他のHTTPキャッシュヘッダーが適切に設定されていることを再確認する必要があります。 適切なHTTPキャッシュヘッダーがないと、ブラウザはlast-modifiedてからの経過時間の10%に自動的に設定され、キャッシュが不足したり過剰になったりする可能性があります。

    一般に、リソースは非常に短時間(変更される可能性がある場合)または無期限(静的な場合)のいずれかでキャッシュ可能である必要があります。必要に応じて、URLのバージョンを変更できます。 これをCache-Forever戦略と呼ぶことができます。この戦略では、 Cache-ControlヘッダーとExpiresヘッダーをブラウザーに中継して、アセットの有効期限が1年のみになるようにすることができます。 したがって、アセットがキャッシュにある場合、ブラウザはアセットを要求することさえしません。

    例外はAPI応答です(例: /api/user )。 キャッシュを防ぐために、 private, no storeを使用でき、 max-age=0, no-storeありません:

     Cache-Control: private, no-store

    Cache-control: immutableを使用して、ユーザーがリロードボタンを押したときに明示的なキャッシュの有効期間が長く再検証されないようにします。 リロードの場合、 immutableはHTTPリクエストを保存し、ダイナミックHTMLが多数の304レスポンスと競合しなくなるため、ダイナミックHTMLのロード時間を改善します。

    immutableを使用したい典型的な例は、名前にハッシュが含まれるCSS / JavaScriptアセットです。 彼らにとっては、おそらくできるだけ長くキャッシュし、再検証されないようにしたいでしょう。

    Cache-Control: max-age: 31556952, immutable

    Colin Bendellの調査によると、 immutableは304リダイレクトを約50%削減します。これは、 max-ageを使用している場合でも、クライアントは更新時に再検証してブロックするためです。 Firefox、Edge、Safariでサポートされており、Chromeはまだこの問題について議論しています。

    Web Almanacによると、「その使用量は3.5%に増加し、FacebookやGoogleのサードパーティの応答で広く使用されています。」

    AndroidChromeおよびiOSSafariから取得したデータを使用した大陸全体でのキャッシュ制御の有効性
    Cache-Control:CloudinaryでのColin Bendellの調査によると、Immutableは304を約50%削減します。 (大プレビュー)

    古き良き再検証中の古さを覚えていますか? Cache-Control応答ヘッダーでキャッシュ時間を指定すると(例: Cache-Control: max-age=604800 )、 max-ageの期限が切れると、ブラウザーは要求されたコンテンツを再フェッチするため、ページの読み込みが遅くなります。 この速度低下は、 stale-while-revalidate使用して回避できます。 基本的に、バックグラウンドで非同期で再検証する限り、キャッシュが古いアセットを使用できる追加の時間枠を定義します。 したがって、(ネットワークとサーバーの両方で)遅延をクライアントから「隠蔽」します。

    2019年6月から7月に、 ChromeとFirefoxはHTTP Cache-Controlヘッダーでstale-while-revalidateサポートを開始しました。その結果、古いアセットがクリティカルパスにないため、後続のページ読み込みの待ち時間が改善されるはずです。 結果:リピートビューのRTTはゼロ。

    特にCDNに関連して、varyヘッダーに注意し、新しいリクエストが以前のリクエストとわずかに(ただし大幅ではない)異なる場合は常に検証のための追加のラウンドトリップを回避するのに役立つHTTP表現バリアントに注意してください(ありがとう、GuyとMark ! )。

    また、不要なヘッダー( x-powered-bypragmax-ua-compatibleexpiresX-XSS-Protectionなど)を送信していないこと、および有用なセキュリティとパフォーマンスのヘッダー( Content-Security-PolicyX-Content-Type-Optionsなどとして)。 最後に、シングルページアプリケーションでのCORSリクエストのパフォーマンスコストに注意してください。

    :キャッシュされたアセットは即座に取得されると想定されることがよくありますが、調査によると、キャッシュからオブジェクトを取得するには数百ミリ秒かかる場合があります。 実際、Simon Hearneによると、「ネットワークはキャッシュよりも高速である場合があり、キャッシュからのアセットの取得は、多数のキャッシュされたアセット(ファイルサイズではない)とユーザーのデバイスでコストがかかる可能性があります。例:ChromeOSの平均キャッシュ取得5つのキャッシュされたリソースで最大50ミリ秒から25のリソースで最大100ミリ秒まで2倍になります。」

    さらに、バンドルサイズは大きな問題ではないと想定されることが多く、ユーザーはバンドルサイズを一度ダウンロードしてから、キャッシュされたバージョンを使用します。 同時に、CI / CDを使用すると、コードを1日に複数回本番環境にプッシュし、キャッシュは毎回無効になるため、キャッシュについて戦略的に取り組むことが重要です。

    キャッシングに関しては、読む価値のあるリソースがたくさんあります。

    • 民間人のためのキャッシュ制御、ハリー・ロバーツによるすべてのキャッシュの詳細。
    • HTTPキャッシングヘッダーに関するHerokuの入門書、
    • JakeArchibaldによるキャッシュのベストプラクティス
    • Ilya GrigorikによるHTTPキャッシング入門書、
    • ジェフ・ポズニックによる再検証中の古いもので物事を新鮮に保つ。
    • CS Visualized:Lydia HallieによるCORSは、CORS、その仕組み、およびその意味を理解する方法についての優れた説明者です。
    • CORSについてお話ししますが、EricPortisによる同一生成元ポリシーについて少し復習します。
右側(上から下)に名前が付けられたさまざまなOSとブラウザでキャッシュされたアセットの数によるキャッシュ取得時間を示すグラフ:デスクトップChrome OS、タブレットAndroid OS、モバイルAndroid OS、デスクトップMac = S X、デスクトップWindows、デスクトップLinux
ブラウザのキャッシュはほぼ瞬時に発生すると想定していますが、データによると、キャッシュからオブジェクトを取得するには数百ミリ秒かかる場合があります。 ネットワークがキャッシュよりも高速である場合に関するSimonHearneの調査から。 (大プレビュー)

配信の最適化

  1. 重要なJavaScriptを非同期でロードするためにdeferを使用しますか?
    ユーザーがページをリクエストすると、ブラウザはHTMLをフェッチしてDOMを構築し、次にCSSをフェッチしてCSSOMを構築し、DOMとCSSOMを照合してレンダリングツリーを生成します。 JavaScriptを解決する必要がある場合、ブラウザは解決されるまでページのレンダリングを開始しないため、レンダリングが遅れます。 開発者として、ブラウザに待機せず、ページのレンダリングを開始するように明示的に指示する必要があります。 スクリプトに対してこれを行う方法は、HTMLのdefer属性とasync属性を使用することです。

    実際には、 asyncの代わりにdeferを使用する方が良いことがわかります。 ああ、また違いは何ですか? Steve Soudersによると、 asyncスクリプトが到着すると、スクリプトの準備ができるとすぐに実行されます。 これが非常に高速に発生する場合、たとえば、スクリプトがキャッシュリーダーにある場合、実際にはHTMLパーサーをブロックできます。 deferを使用すると、ブラウザはHTMLが解析されるまでスクリプトを実行しません。 したがって、レンダリングを開始する前にJavaScriptを実行する必要がない限り、 deferを使用することをお勧めします。 また、複数の非同期ファイルは非決定論的な順序で実行されます。

    asyncdeferについては、いくつかの誤解があることに注意してください。 最も重要なことは、 asyncは、スクリプトの準備ができたときにコードが実行されることを意味するわけではありません。 これは、スクリプトの準備が整い先行するすべての同期作業が完了するたびに実行されることを意味します。 ハリー・ロバーツの言葉によれば、「同期スクリプトの後にasyncスクリプトを配置すると、 asyncスクリプトは最も遅い同期スクリプトと同じくらい速くなります。」

    また、 asyncdeferの両方を使用することはお勧めしません。 最新のブラウザは両方をサポートしていますが、両方の属性が使用されている場合は常に、 asyncが優先されます。

    詳細を詳しく知りたい場合は、Milica Mihajlijaが、投機的構文解析、非同期、および延期の詳細について、DOMの高速構築に関する非常に詳細なガイドを作成しました。

  2. IntersectionObserverと優先度のヒントを使用して、高価なコンポーネントを遅延ロードします。
    一般に、重いJavaScript、ビデオ、iframe、ウィジェット、場合によっては画像など、高価なコンポーネントをすべて遅延読み込みすることをお勧めします。 ネイティブの遅延読み込みは、 loading属性を持つ画像とiframeですでに利用可能です(Chromiumのみ)。 内部的には、この属性は、ビューポートから計算された距離に達するまで、リソースのロードを延期します。
    <!-- Lazy loading for images, iframes, scripts. Probably for images outside of the viewport. --> <img loading="lazy" ... /> <iframe loading="lazy" ... /> <!-- Prompt an early download of an asset. For critical images, eg hero images. --> <img loading="eager" ... /> <iframe loading="eager" ... />

    そのしきい値は、フェッチされる画像リソースのタイプから有効な接続タイプまで、いくつかの要因に依存します。 ただし、AndroidでChromeを使用して実施された実験によると、4Gでは、遅延読み込みされた折り畳み下の画像の97.5%が、表示されてから10ミリ秒以内に完全に読み込まれたため、安全であるはずです。

    <script><img> 、または<link>要素でimportance属性( highまたはlow )を使用することもできます(点滅のみ)。 実際、カルーセル内の画像の優先順位を下げたり、スクリプトの優先順位を付け直したりするのに最適な方法です。 ただし、場合によっては、もう少しきめ細かい制御が必要になることがあります。

    <!-- When the browser assigns "High" priority to an image, but we don't actually want that. --> <img src="less-important-image.svg" importance="low" ... /> <!-- We want to initiate an early fetch for a resource, but also deprioritize it. --> <link rel="preload" importance="low" href="/script.js" as="script" />

    少し洗練された遅延読み込みを行う最もパフォーマンスの高い方法は、Intersection Observer APIを使用することです。これは、ターゲット要素と祖先要素またはトップレベルドキュメントのビューポートとの交差の変化を非同期的に監視する方法を提供します。 基本的に、コールバック関数と一連のオプションを受け取る新しいIntersectionObserverオブジェクトを作成する必要があります。 次に、観察するターゲットを追加します。

    コールバック関数は、ターゲットが表示または非表示になったときに実行されるため、ビューポートをインターセプトすると、要素が表示される前にいくつかのアクションを開始できます。 実際、 rootMargin (ルートの周囲のマージン)とthreshold (ターゲットの可視性の何パーセントを目指しているかを示す単一の数値または数値の配列)を使用して、オブザーバーのコールバックを呼び出すタイミングをきめ細かく制御できます。

    Alejandro Garcia Angladaは、実際に実装する方法に関する便利なチュートリアルを公開しています。RahulNanwaniは、遅延読み込みの前景と背景の画像に関する詳細な投稿を作成しました。GoogleFundamentalsは、交差点オブザーバーを使用した遅延読み込みの画像と動画に関する詳細なチュートリアルも提供しています。

    アート指向のストーリーテリングで、動くオブジェクトや粘着性のあるオブジェクトを使った長い読み物を覚えていますか? IntersectionObserverを使用してパフォーマンスの高いスクロールテリングを実装することもできます。

    他に遅延読み込みできるものをもう一度確認してください。 遅延読み込みの翻訳文字列や絵文字でさえ役立つ可能性があります。 そうすることで、モバイルTwitterは、新しい国際化パイプラインからJavaScriptの実行を80%高速化することができました。

    ただし、簡単に注意してください。遅延読み込みは、ルールではなく例外である必要があることに注意してください。 製品ページの画像、ヒーロー画像、メインナビゲーションをインタラクティブにするために必要なスクリプトなど、実際に人々にすばやく見てもらいたいものを遅延読み込みするのはおそらく合理的ではありません。

160KBのダウンロードで3000pxの古いしきい値を示す例(左)、新しいしきい値の量は1250pxで、ダウンロードは90KBのみ(右)で、imgの読み込みの遅延データの節約が改善されていることを示しています。
高速接続(例:4G)では、Chromeのビューポートからの距離のしきい値が最近3000pxから1250pxに減少し、低速接続(例:3G)では、しきい値が4000pxから2500pxに変更されました。 (大プレビュー)
Twitter UIが表示された携帯電話の周りにテキストが表示されたイラストで、遅延読み込みの翻訳文字列によるツールの改善について説明しています。
モバイルTwitterは、翻訳文字列を遅延読み込みすることで、新しい国際化パイプラインからJavaScriptの実行を80%高速化することに成功しました。 (画像クレジット:Addy Osmani)(大プレビュー)
  1. 画像を段階的にロードします。
    ページにプログレッシブ画像の読み込みを追加することで、遅延読み込みを次のレベルに引き上げることもできます。 Facebook、Pinterest、Medium、Woltと同様に、最初に低品質またはぼやけた画像を読み込んでから、ページの読み込みを続けながら、BlurHashテクニックまたはLQIP(低品質画像プレースホルダー)を使用してフル品質バージョンに置き換えます。技術。

    これらの手法によってユーザーエクスペリエンスが向上するかどうかについては意見が異なりますが、First ContentfulPaintまでの時間は確実に向上します。 低品質バージョンの画像をSVGプレースホルダーとして作成するSQIP、またはCSS線形グラデーションを使用したグラデーション画像プレースホルダーを使用して自動化することもできます。

    これらのプレースホルダーは、テキスト圧縮メソッドで自然に圧縮されるため、HTML内に埋め込むことができます。 Dean Humeは、彼の記事で、IntersectionObserverを使用してこの手法を実装する方法について説明しています。

    後退する? ブラウザが交差点オブザーバーをサポートしていない場合でも、ポリフィルを遅延ロードするか、画像をすぐにロードできます。 そして、そのためのライブラリもあります。

    もっと空想に行きたいですか? 画像をトレースし、プリミティブシェイプとエッジを使用して、軽量のSVGプレースホルダーを作成し、最初にロードしてから、プレースホルダーベクトルイメージから(ロードされた)ビットマップイメージに遷移することができます。

  2. Jose M. PerezによるSVG遅延読み込み手法を示す3つの異なるバージョン、左側にキュービズムアートに類似したバージョン、中央にピクセル化されたぼやけたバージョン、右側にJose自身の適切な写真
    Jose M.PerezによるSVG遅延読み込み手法。 (大プレビュー)
  3. content-visibilityでレンダリングを延期しますか?
    豊富なコンテンツブロック、画像、ビデオを含む複雑なレイアウトの場合、データのデコードとピクセルのレンダリングは、特にローエンドデバイスでは、非常にコストのかかる操作になる可能性があります。 content-visibility: autoを使用すると、コンテナーがビューポートの外にある間、ブラウザーに子のレイアウトをスキップするように求めることができます。

    たとえば、初期ロード時にフッターと後期セクションのレンダリングをスキップできます。

    footer { content-visibility: auto; contain-intrinsic-size: 1000px; /* 1000px is an estimated height for sections that are not rendered yet. */ }

    content-visibility:auto;に注意してください。 オーバーフローのように動作します:非表示。 、ただし、デフォルトのmargin-leftの代わりにpadding padding-leftpadding-rightを適用することで修正できますmargin-left: auto;margin-right: auto; と宣言された幅。 パディングを使用すると、基本的に、要素がコンテンツボックスをオーバーフローして、ボックスモデル全体を離れたり、切り取られたりすることなく、パディングボックスに入ることができます。

    また、新しいコンテンツが最終的にレンダリングされるときにCLSが導入される可能性があることに注意してください。そのため、適切なサイズのプレースホルダーを使用しcontain-intrinsic-sizeを使用することをお勧めします(ありがとう、Una! )。

    Thijs Terluinには、両方のプロパティと、ブラウザによるcontain-intrinsic-sizeの計算方法に関する詳細があり、Malte Ublはそれを計算する方法を示し、JakeとSurmaによる簡単なビデオ説明者がすべての動作を説明しています。

    また、CSS Containmentを使用してもう少し細かくする必要がある場合は、他の要素のサイズ、配置、または計算されたスタイルのみが必要な場合、または要素が現在ある場合は、DOMノードの子孫のレイアウト、スタイル、およびペイント作業を手動でスキップできます。オフキャンバス。

初期ロードでのレンダリングパフォーマンスは、ベースライン(左)で2,288ミリ秒、content-visibility:auto(右)のチャンクで13,464ミリ秒です。
デモでは、 content-visibility: autoをチャンク化されたコンテンツ領域に適用すると、初期ロード時にレンダリングパフォーマンスが7倍向上します。 (大プレビュー)
  1. decode decoding="async"を延期しますか?
    コンテンツが画面外に表示されることもありますが、お客様が必要なときにコンテンツを利用できるようにする必要があります。理想的には、クリティカルパスで何もブロックせず、非同期でデコードおよびレンダリングします。 decode decoding="async"を使用して、メインスレッドから画像をデコードする許可をブラウザに与えることができます。これにより、(Malte Ublを介して)画像のデコードに使用されるCPU時間のユーザーへの影響を回避できます。

    <img decoding="async" … />

    または、オフスクリーン画像の場合、最初にプレースホルダーを表示し、画像がビューポート内にあるときに、IntersectionObserverを使用して、画像をバックグラウンドでダウンロードするためのネットワーク呼び出しをトリガーできます。 また、img.decode()でデコードするまでレンダリングを延期するか、Image DecodeAPIが利用できない場合は画像をダウンロードすることができます。

    画像をレンダリングするとき、たとえばフェードインアニメーションを使用できます。 KatieHempeniusとAddyOsmaniは、彼らの講演「Speed at Scale:Web Performance Tips and Tricks fromtheTrenches」でより多くの洞察を共有しています。

  2. 重要なCSSを生成して提供していますか?
    ブラウザができるだけ早くページのレンダリングを開始できるようにするために、ページの最初の表示部分のレンダリングを開始するために必要なすべてのCSS(「クリティカルCSS」または「オーバーザフォールドCSS」と呼ばれる)を収集することが一般的な方法になりました。 ")そしてそれをページの<head>にインラインで含めることで、ラウンドトリップを減らします。 スロースタートフェーズ中に交換されるパッケージのサイズが限られているため、重要なCSSの予算は約14KBです。

    それを超えると、ブラウザはより多くのスタイルをフェッチするために追加のラウンドトリップが必要になります。 CriticalCSSとCriticalを使用すると、使用しているすべてのテンプレートの重要なCSSを出力できます。 しかし、私たちの経験では、すべてのテンプレートの重要なCSSを手動で収集するよりも優れた自動システムはありません。実際、これが最近戻ってきたアプローチです。

    次に、重要なCSSをインライン化し、残りをcrittersWebpackプラグインで遅延ロードできます。 可能であれば、フィラメントグループで使用される条件付きインライン化アプローチを使用するか、インラインコードをその場で静的アセットに変換することを検討してください。

    現在、loadCSSなどのライブラリを使用して完全なCSSを非同期でロードしている場合、実際には必要ありません。 media="print"を使用すると、ブラウザをだましてCSSを非同期にフェッチさせることができますが、ロードされると画面環境に適用されます。 (ありがとう、スコット!

    <!-- Via Scott Jehl. https://www.filamentgroup.com/lab/load-css-simpler/ --> <!-- Load CSS asynchronously, with low priority --> <link rel="stylesheet" href="full.css" media="print" onload="this.media='all'" />

    各テンプレートのすべての重要なCSSを収集するときは、「折り畳みの上」の領域だけを探索するのが一般的です。 ただし、複雑なレイアウトの場合は、レイアウトの基礎も含めて、大量の再計算と再描画のコストを回避し、結果としてCore WebVitalsスコアを損なうことを回避することをお勧めします。

    ユーザーがページの中央に直接リンクしているURLを取得したが、CSSがまだダウンロードされていない場合はどうなりますか? その場合、重要ではないコンテンツを非表示にすることが一般的になりました。たとえば、 opacity: 0; インラインCSSおよびopacity: 1 、CSSが使用可能な場合に表示します。 ただし、接続速度が遅いユーザーはページのコンテンツを読み取ることができない可能性があるため、大きな欠点があります。 そのため、適切なスタイルが設定されていない場合でも、コンテンツは常に表示されたままにしておくことをお勧めします。

    重要なCSS(およびその他の重要なアセット)をルートドメインの別のファイルに配置すると、キャッシュが原因で、インライン化よりも多くの利点があります。 Chromeは、ページをリクエストするときにルートドメインへの2番目のHTTP接続を投機的に開きます。これにより、このCSSをフェッチするためのTCP接続が不要になります。 つまり、重要な-CSSファイルのセット(たとえば、 critical-homepage.csscritical-product-page.cssなど)を作成し、それらをインライン化することなく、ルートから提供できます。 (ありがとう、フィリップ!

    注意:HTTP / 2を使用すると、重要なCSSを別のCSSファイルに保存し、HTMLを肥大化させることなくサーバープッシュを介して配信できます。 キャッチは、サーバーのプッシュがブラウザ間での多くの落とし穴と競合状態で厄介だったことです。 一貫してサポートされることはなく、キャッシュの問題がいくつかありました(Hooman Beheshtiのプレゼンテーションのスライド114以降を参照)。

    実際、この影響はマイナスになり、ネットワークバッファが肥大化し、ドキュメント内の本物のフレームが配信されなくなる可能性があります。 そのため、当面の間、Chromeがサーバープッシュのサポートを削除することを計画していることはそれほど驚くことではありませんでした。

  3. CSSルールを再グループ化してみてください。
    重要なCSSには慣れていますが、それを超える可能性のある最適化がいくつかあります。 ハリー・ロバーツは驚くべき研究を行い、驚くべき結果をもたらしました。 たとえば、メインのCSSファイルを個々のメディアクエリに分割することをお勧めします。 このようにして、ブラウザは優先度の高い重要なCSSを取得し、優先度の低い他のすべてのものを取得します—完全にクリティカルパスから外れます。

    また、 asyncスニペットの前に<link rel="stylesheet" />を配置することは避けてください。 スクリプトがスタイルシートに依存しない場合は、ブロックするスタイルの上にブロックするスクリプトを配置することを検討してください。 その場合は、そのJavaScriptを2つに分割し、CSSのいずれかの側にロードします。

    Scott Jehlは、インラインCSSファイルをService Workerでキャッシュすることで、別の興味深い問題を解決しました。これは、重要なCSSを使用している場合によくある問題です。 基本的に、JavaScriptを使用して簡単に見つけられるようにstyle要素にID属性を追加します。次に、JavaScriptの小さな部分がそのCSSを見つけ、Cache APIを使用してローカルブラウザキャッシュに保存します(コンテンツタイプはtext/css )。 text/css )以降のページで使用します。 後続のページにインライン化することを避け、代わりにキャッシュされたアセットを外部から参照するために、サイトへの最初のアクセス時にCookieを設定します。 出来上がり!

    動的なスタイリングも高価になる可能性があることに注意してください。ただし、通常は、同時にレンダリングされる何百もの構成されたコンポーネントに依存している場合に限ります。 したがって、CSS-in-JSを使用している場合は、CSSがテーマや小道具に依存していないときにCSS-in-JSライブラリが実行を最適化し、スタイル付きコンポーネントを過剰に構成しないようにしてください。 Aggelos Arvanitakisは、CSS-in-JSのパフォーマンスコストに関するより多くの洞察を共有しています。

  4. 応答をストリーミングしますか?
    忘れられたり無視されたりすることが多いストリームは、データの非同期チャンクを読み書きするためのインターフェイスを提供します。そのサブセットのみが、いつでもメモリで使用できる可能性があります。 基本的に、元のリクエストを行ったページは、データの最初のチャンクが利用可能になるとすぐにレスポンスの処理を開始でき、ストリーミング用に最適化されたパーサーを使用してコンテンツを段階的に表示できます。

    複数のソースから1つのストリームを作成できます。 たとえば、空のUIシェルを提供してJavaScriptにデータを入力させる代わりに、シェルがキャッシュから取得され、本体がネットワークから取得されるストリームをServiceWorkerに構築させることができます。 Jeff Posnickが指摘したように、Webアプリが部分的なテンプレートをつなぎ合わせてHTMLをサーバーレンダリングするCMSを利用している場合、そのモデルは、サーバーではなくService Workerで複製されたテンプレートロジックを使用して、ストリーミング応答を使用するように直接変換されます。 JakeArchibaldのTheYear of Web Streamsの記事は、それをどのように正確に構築できるかを強調しています。 パフォーマンスの向上は非常に顕著です。

    HTML応答全体をストリーミングすることの重要な利点の1つは、最初のナビゲーション要求中にレンダリングされたHTMLが、ブラウザーのストリーミングHTMLパーサーを最大限に活用できることです。 ページの読み込み後にドキュメントに挿入されるHTMLのチャンク(JavaScriptを介して入力されたコンテンツで一般的)は、この最適化を利用できません。

    ブラウザのサポート? Chrome、Firefox、Safari、Edgeで部分的にサポートされており、最新のすべてのブラウザーでサポートされているAPIとServiceWorkerをサポートしています。 また、冒険心があれば、ストリーミングリクエストの実験的な実装を確認できます。これにより、本文を生成しながらリクエストの送信を開始できます。 Chrome85で利用できます。

Android Chromeでのデータ保存の使用状況と、2019年11月と2020年4月にCloudinaryの調査で発見された平均imgヒットまたはセッションをまとめた画像
Cloudinaryの調査によると、世界中のAndroid Chromeユーザーの18%がLiteモード(別名Save-Data)を有効にしています。 (大プレビュー)
  1. コンポーネントを接続対応にすることを検討してください。
    データは高額になる可能性があり、ペイロードが増えるにつれて、サイトやアプリにアクセスする際にデータの節約を選択するユーザーを尊重する必要があります。 Save-Dataクライアントヒントリクエストヘッダーを使用すると、コストとパフォーマンスに制約のあるユーザー向けにアプリケーションとペイロードをカスタマイズできます。

    実際、高DPI画像のリクエストを低DPI画像に書き換えたり、ウェブフォント、派手な視差効果を削除したり、サムネイルと無限スクロールをプレビューしたり、動画の自動再生をオフにしたり、サーバーをプッシュしたり、表示されるアイテムの数を減らしたり、画質をダウングレードしたりできます。マークアップの配信方法も変更します。 Tim Vereeckeは、データ保存の多くのオプションを特徴とするdata-s(h)aver戦略に関する非常に詳細な記事を公開しました。

    誰がsave-dataを使用していますか、あなたは疑問に思うかもしれませんか? 世界のAndroidChromeユーザーの18%がライトモードを有効にしており( Save-Dataオン)、その数はもっと多くなる可能性があります。 Simon Hearneの調査によると、オプトイン率は安価なデバイスで最も高くなりますが、外れ値はたくさんあります。 例:カナダのユーザーのオプトイン率は34%を超え(米国の約7%と比較して)、最新のSamsungフラッグシップのユーザーのオプトイン率は世界全体でほぼ18%です。

    [ Save-Data ]モードをオンにすると、Chrome Mobileは最適化されたエクスペリエンスを提供します。つまり、遅延スクリプト、強制されたfont-display: swap 、および強制された遅延読み込みを使用したプロキシWebエクスペリエンスを提供します。 これらの最適化を行うためにブラウザに依存するよりも、自分でエクスペリエンスを構築する方が賢明です。

    ヘッダーは現在、Chromium、AndroidバージョンのChrome、またはデスクトップデバイスのデータセーバー拡張機能でのみサポートされています。 最後に、Network Information APIを使用して、ネットワークタイプに基づいて、コストのかかるJavaScriptモジュール、高解像度の画像およびビデオを配信することもできます。 ネットワーク情報API、特にnavigator.connection.effectiveTypeは、 RTTdownlinkeffectiveType値(およびその他のいくつか)を使用して、ユーザーが処理できる接続とデータの表現を提供します。

    このコンテキストでは、Max Bockは接続対応コンポーネントについて話し、AddyOsmaniは適応モジュールサービングについて話します。 たとえば、Reactを使用すると、接続タイプごとに異なるレンダリングを行うコンポーネントを作成できます。 Maxが示唆したように、ニュース記事の<Media />コンポーネントは次のように出力する可能性があります。

    • Offlinealtテキストを含むプレースホルダー、
    • 2G / save-dataモード:低解像度画像、
    • 非Retina画面での3G :中解像度の画像、
    • Retina画面の3G :高解像度のRetina画像、
    • 4G :HDビデオ。

    Dean Humeは、ServiceWorkerを使用して同様のロジックの実用的な実装を提供します。 ビデオの場合、デフォルトでビデオポスターを表示してから、「再生」アイコン、ビデオプレーヤーシェル、ビデオのメタデータなどをより適切な接続で表示できます。 サポートされていないブラウザのフォールバックとして、 canplaythroughイベントをリッスンし、 canplaythroughイベントが2秒以内に発生しない場合は、 Promise.race()を使用してソースの読み込みをタイムアウトすることができます。

    もう少し深く掘り下げたい場合は、開始するためのリソースがいくつかあります。

    • Addy Osmaniは、Reactでアダプティブサービングを実装する方法を示しています。
    • React Adaptive Loading Hooks&Utilitiesは、Reactのコードスニペットを提供します。
    • Netanel Baselは、Angularの接続対応コンポーネントを調査します。
    • Theodore Vorilasが、Vueでネットワーク情報APIを使用してアダプティブコンポーネントを提供する方法について説明します。
    • Umar Hansaは、高価なJavaScriptを選択的にダウンロード/実行する方法を示しています。
  2. コンポーネントをデバイスメモリ対応にすることを検討してください。
    ただし、ネットワーク接続では、ユーザーのコンテキストで1つの視点しか得られません。 さらに、Device Memory APIを使用して、使用可能なデバイスメモリに基づいてリソースを動的に調整することもできます。 navigator.deviceMemoryは、デバイスに搭載されているRAMの量をギガバイト単位で返し、最も近い2の累乗に切り捨てられます。 APIは、同じ値を報告するクライアントヒントヘッダーであるDevice-Memoryも備えています。

    ボーナスUmar Hansaは、動的インポートを使用して高価なスクリプトを延期し、デバイスメモリ、ネットワーク接続、およびハードウェアの同時実行性に基づいてエクスペリエンスを変更する方法を示しています。

Chrome46以降のBlinkでさまざまなリソースがどのように優先されているかを示す内訳
Chrome46以降のBlinkでさまざまなリソースがどのように優先されているかを示す内訳。 (画像クレジット:Addy Osmani)(大プレビュー)
  1. 接続をウォームアップして配信を高速化します。
    リソースヒントを使用して、 dns-prefetch (バックグラウンドでDNSルックアップを実行する)、 preconnect (ブラウザーにバックグラウンドで接続ハンドシェイク(DNS、TCP、TLS)を開始するように要求する)、 prefetch (ブラウザーに要求する)の時間を節約しますリソースを要求するため)およびpreload (特に、リソースを実行せずにプリフェッチします)。 最新のブラウザで十分にサポートされており、Firefoxでもまもなくサポートされる予定です。

    prerender覚えていますか? 次のナビゲーションのためにバックグラウンドでページ全体を構築するようにブラウザに促すために使用されるリソースヒント。 実装の問題は非常に問題があり、膨大なメモリフットプリントや帯域幅の使用から、複数の登録された分析ヒットや広告の表示回数にまで及びました。

    当然のことながら、これは非推奨になりましたが、ChromeチームはNoStateプリフェッチメカニズムとして復活させました。 実際、Chromeは事前レンダリングヒントを代わりにprerenderプリフェッチとして扱うため、今日でも使用できます。 Katie Hempeniusがその記事で説明しているように、「事前レンダリングと同様に、 NoState Prefetchは事前にリソースをフェッチしますが、事前レンダリングとは異なり、 JavaScriptを実行したり、ページの一部を事前にレンダリングしたりすることはありません。」

    NoStateプリフェッチは最大45MiBのメモリのみを使用し、フェッチされるサブリソースはIDLEネットプライオリティでフェッチされます。 Chrome 69以降、 NoState Prefetchは、通常のブラウジングと区別できるようにするために、すべてのリクエストにヘッダープリフェッチを追加します。

    また、プライバシーを意識した事前レンダリングに向けた新たな取り組みである事前レンダリングの選択肢とポータルにも注意してください。これにより、シームレスなナビゲーションのためにコンテンツのはめ込みpreviewが提供されます。

    リソースヒントを使用することは、おそらくパフォーマンスを向上させる最も簡単な方法であり、実際にうまく機能します。 いつ何を使うの? Addy Osmaniが説明したように、現在のページや、ユーザーがまだアクセスしていないページに必要なWebpackバンドルなど、複数のナビゲーション境界を越えた将来のナビゲーションに使用される可能性が非常に高いことがわかっているリソースをプリロードすることは合理的です。

    Addyの「Chromeでの優先度の読み込み」に関する記事では、Chromeがリソースヒントを正確に解釈する方法を示しています。したがって、レンダリングに重要なアセットを決定したら、それらに高い優先度を割り当てることができます。 リクエストがどのように優先されるかを確認するには、Chrome DevToolsネットワークリクエストテーブル(およびSafari)で「優先度」列を有効にします。

    最近のほとんどの場合、少なくともpreconnectdns-prefetchを使用し、 prefetchpreloadprerenderの使用には注意が必要です。 preconnectdns-prefetchを使用しても、ブラウザには並行して検索/接続するホストの数に制限があるため、優先度に基づいて注文するのが安全です( PhilipTellisに感謝します)。

    フォントは通常、ページ上の重要なアセットであるため、 preloadを使用して重要なフォントをダウンロードするようにブラウザに要求することをお勧めします。 ただし、フォントをプリロードするときに優先順位のパズルがあるため、実際にパフォーマンスに役立つかどうかを再確認してください。 preloadは非常に重要であると見なされているため、重要なCSSなどのさらに重要なリソースを飛躍させることができます。 (ありがとう、バリー!

    <!-- Loading two rendering-critical fonts, but not all their weights. --> <!-- crossorigin="anonymous" is required due to CORS. Without it, preloaded fonts will be ignored. https://github.com/w3c/preload/issues/32 via https://twitter.com/iamakulov/status/1275790151642423303 --> <link rel="preload" as="font" href="Elena-Regular.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" /> <link rel="preload" as="font" href="Mija-Bold.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" />
    <!-- Loading two rendering-critical fonts, but not all their weights. --> <!-- crossorigin="anonymous" is required due to CORS. Without it, preloaded fonts will be ignored. https://github.com/w3c/preload/issues/32 via https://twitter.com/iamakulov/status/1275790151642423303 --> <link rel="preload" as="font" href="Elena-Regular.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" /> <link rel="preload" as="font" href="Mija-Bold.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" />

    <link rel="preload">media属性を受け入れるため、上記のように、 @mediaクエリルールに基づいてリソースを選択的にダウンロードすることを選択できます。

    さらに、 imagesizes imagesrcsetを使用して、最近発見されたヒーロー画像や、JavaScriptを介して読み込まれる画像(映画のポスターなど)をより速くプリロードできます。

    <!-- Addy Osmani. https://addyosmani.com/blog/preload-hero-images/ --> <link rel="preload" as="image" href="poster.jpg" image image>
    <!-- Addy Osmani. https://addyosmani.com/blog/preload-hero-images/ --> <link rel="preload" as="image" href="poster.jpg" image image>

    JSONをfetchとしてプリロードすることもできるため、JavaScriptがJSONを要求する前にJSONが検出されます。

    <!-- Addy Osmani. https://addyosmani.com/blog/preload-hero-images/ --> <link rel="preload" as="fetch" href="foo.com/api/movies.json" crossorigin>

    スクリプトを怠惰に実行するために、JavaScriptを動的に効果的にロードすることもできます。

    /* Adding a preload hint to the head */ var preload = document.createElement("link"); link.href = "myscript.js"; link.rel = "preload"; link.as = "script"; document.head.appendChild(link); /* Injecting a script when we want it to execute */ var script = document.createElement("script"); script.src = "myscript.js"; document.body.appendChild(script);

    覚えておくべきいくつかの落とし穴: preloadは、アセットのダウンロード開始時間を最初のリクエストに近づけるのに適していますが、プリロードされたアセットは、リクエストを行うページに関連付けられているメモリキャッシュに格納されます。 preloadはHTTPキャッシュでうまく機能します。アイテムがすでにHTTPキャッシュにある場合、ネットワーク要求は送信されません。

    したがって、最近発見されたリソース、 background-imageを介して読み込まれたヒーロー画像、重要なCSS(またはJavaScript)のインライン化、残りのCSS(またはJavaScript)の事前読み込みに役立ちます。

    トムハンクス主演のグレイハウンド映画の表紙を使用して、JavaScriptで検出するのを待つ必要がないため、プリロードされた画像が早く読み込まれることを示す例
    重要な画像を早期にプリロードします。 それらを発見するためにJavaScriptを待つ必要はありません。 (画像クレジット:AddyOsmaniによる「PreloadLate-DiscoveredHero Images Faster」)(大プレビュー)

    preloadタグは、ブラウザがサーバーからHTMLを受信し、先読みパーサーがpreloadタグを検出した後でのみ、プリロードを開始できます。 ブラウザがHTMLを解析してリクエストを開始するのを待たないため、HTTPヘッダーを介したプリロードは少し速くなる可能性があります(ただし、議論されています)。

    初期のヒントはさらに役立ち、HTMLの応答ヘッダーが送信される前でもプリロードを開始できるようにします(Chromium、Firefoxのロードマップ上)。 さらに、優先度のヒントは、スクリプトの読み込みの優先度を示すのに役立ちます。

    注意preloadを使用している場合は、定義as必要があるか、何もロードしない場合に加えて、 crossorigin属性のないプリロードされたフォントはダブルフェッチされます。 prefetchを使用している場合は、FirefoxのAgeヘッダーの問題に注意してください。

所定の期間(ミリ秒単位)でカウントが0から150の最初の満足のいくペイント(サーバーワーカーのステータス別)を示すグラフ
Service Workerを使用すると、最小限のデータを要求し、そのデータを完全なHTMLドキュメントに変換してFCPを向上させることができます。 (Phil Walton経由)(大プレビュー)
  1. キャッシングとネットワークフォールバックにサービスワーカーを使用します。
    ネットワーク上でのパフォーマンスの最適化は、ユーザーのマシンにローカルに保存されたキャッシュよりも高速になることはありません(ただし例外があります)。 WebサイトがHTTPSで実行されている場合、静的アセットをService Workerキャッシュにキャッシュし、オフラインフォールバック(またはオフラインページ)を保存して、ネットワークにアクセスするのではなく、ユーザーのマシンから取得できます。

    Phil Waltonが提案したように、Service Workerを使用すると、プログラムで応答を生成することで、より小さなHTMLペイロードを送信できます。 サービスワーカーは、サーバーに必要な最小限のデータ(たとえば、HTMLコンテンツの部分、Markdownファイル、JSONデータなど)を要求し、プログラムでそのデータを完全なHTMLドキュメントに変換できます。 したがって、ユーザーがサイトにアクセスしてService Workerがインストールされると、ユーザーは完全なHTMLページを再度要求することはありません。 パフォーマンスへの影響は非常に印象的です。

    ブラウザのサポート? サービスワーカーは広くサポートされており、フォールバックはとにかくネットワークです。 パフォーマンスの向上に役立ちますか? そうそう、そうです。 また、Background Fetchを使用すると、ServiceWorkerを介したバックグラウンドのアップロード/ダウンロードも可能になります。

    サービスワーカーのユースケースは多数あります。 たとえば、「オフライン用に保存」機能を実装したり、壊れた画像を処理したり、タブ間にメッセージングを導入したり、リクエストの種類に基づいてさまざまなキャッシュ戦略を提供したりできます。 一般に、一般的な信頼できる戦略は、アプリシェルを、オフラインページ、フロントページなど、ケースで重要になる可能性のあるいくつかの重要なページとともに、ServiceWorkerのキャッシュに保存することです。

    ただし、覚えておくべきいくつかの落とし穴があります。 サービスワーカーが配置されている場合、Safariでの範囲リクエストに注意する必要があります(サービスワーカーにWorkboxを使用している場合は、範囲リクエストモジュールがあります)。 DOMException: Quota exceeded. ブラウザコンソールでエラーが発生した場合は、Gerardoの記事「7KBが7MBに等しい場合」を調べてください。

    Gerardoは次のように述べています。「プログレッシブウェブアプリを構築していて、サービスワーカーがCDNから提供される静的アセットをキャッシュするときにキャッシュストレージが肥大化する場合は、クロスオリジンリソースに適切なCORS応答ヘッダーが存在することを確認してください。不透明な応答はキャッシュしないでください。サービスワーカーが意図せずに、クロスcrossorigin属性を<img>タグに追加することで、クロスオリジンイメージアセットをCORSモードにオプトインします。」

    サービスワーカーを始めるための優れたリソースはたくさんあります。

    • サービスワーカーの考え方。これは、サービスワーカーが舞台裏でどのように機能するか、およびサービスワーカーを構築するときに理解することを理解するのに役立ちます。
    • Chris Ferdinandiは、サービスワーカーに関する一連のすばらしい記事を提供し、オフラインアプリケーションの作成方法を説明し、最近表示したページをオフラインで保存する方法から、サービスワーカーのキャッシュにアイテムの有効期限を設定する方法まで、さまざまなシナリオをカバーしています。

    • サービスワーカーの落とし穴とベストプラクティス、スコープに関するいくつかのヒント、サービスワーカーの登録とサービスワーカーのキャッシュの遅延。
    • Ire Aderinokunによる、Service Workerによる「オフラインファースト」の素晴らしいシリーズで、アプリシェルのプリキャッシングに関する戦略があります。
    • Service Worker:豊富なオフラインエクスペリエンス、定期的なバックグラウンド同期、プッシュ通知のためにServiceWorkerを使用する方法に関する実用的なヒントの紹介。
    • 古き良きジェイク・アーチボルドのオフラインクックブックを参照して、自分のサービスワーカーを焼く方法に関するレシピをいくつか紹介することは常に価値があります。
    • Workboxは、プログレッシブWebアプリを構築するために特別に構築されたServiceWorkerライブラリのセットです。
  2. たとえばA / Bテストのために、CDN / Edgeでサーバーワーカーを実行していますか?
    この時点では、クライアントでサービスワーカーを実行することにかなり慣れていますが、CDNをサーバーに実装すると、エッジでのパフォーマンスを微調整するためにも使用できます。

    たとえば、A / Bテストでは、HTMLがユーザーごとにコンテンツを変更する必要がある場合、CDNサーバー上のServiceWorkerを使用してロジックを処理できます。 HTMLの書き換えをストリーミングして、GoogleFontsを使用するサイトを高速化することもできます。

2016年1月から2020年7月までの時間の経過に伴うページの割合を含む、デスクトップとモバイルでのServiceWorkerのインストールの時系列を示すグラフ
ServiceWorkerのインストールの時系列。 Web Almanacによると、すべてのデスクトップページの0.87%だけがサービスワーカーを登録しています。 (大プレビュー)
  1. レンダリングパフォーマンスを最適化します。
    アプリケーションが遅いときはいつでも、すぐに目立ちます。 したがって、ページをスクロールするとき、または要素がアニメーション化されるときにラグがないこと、および1秒あたり60フレームを常にヒットしていることを確認する必要があります。 それが不可能な場合は、少なくとも1秒あたりのフレーム数を一定にすることが60〜15の混合範囲よりも望ましいです。CSSのwill-changeを使用して、どの要素とプロパティが変更されるかをブラウザに通知します。

    発生しているときはいつでも、DevToolsで不要な再描画をデバッグしてください。

    • ランタイムレンダリングのパフォーマンスを測定します。 それを理解する方法に関するいくつかの役立つヒントを確認してください。
    • 開始するには、ブラウザレンダリングの最適化に関するPaul Lewisの無料のUdacityコースと、ブラウザのペイントとWebパフォーマンスに関する考慮事項に関するGeorgyMarchukの記事を確認してください。
    • FirefoxDevToolsの「その他のツール→レンダリング→ペイントフラッシュ」でペイントフラッシュを有効にします。
    • React DevToolsで、[更新を強調表示]をオンにし、[各コンポーネントがレンダリングされた理由を記録する]を有効にします。
    • また、Why Did You Renderを使用することもできるため、コンポーネントが再レンダリングされると、フラッシュが変更を通知します。

    組積造のレイアウトを使用していますか? 間もなく、CSSグリッドだけで石積みレイアウトを構築できる可能性があることに注意してください。

    このトピックをさらに深く掘り下げたい場合は、Nolan Lawsonが彼の記事でレイアウトのパフォーマンスを正確に測定するための秘訣を共有しており、JasonMillerも代替手法を提案しています。 また、GPUアニメーションを正しくする方法についてのSergeyChikuyonokによるlilの記事があります。

    位置、スケール、回転、不透明度などの高性能アニメーション
    ブラウザは、変換と不透明度を安価にアニメーション化できます。 CSSトリガーは、CSSがリレイアウトまたはリフローをトリガーするかどうかを確認するのに役立ちます。 (画像クレジット:Addy Osmani)(大プレビュー)

    :GPU合成レイヤーへの変更は最も安価であるため、 opacitytransformを介して合成のみをトリガーすることで回避できる場合は、正しい方向に進んでいます。 Anna Migasは、UIレンダリングパフォーマンスのデバッグに関する講演でも多くの実践的なアドバイスを提供しています。 また、DevToolsでペイントパフォーマンスをデバッグする方法を理解するには、Umarのペイントパフォーマンス監査ビデオを確認してください。

  2. 知覚されるパフォーマンスに合わせて最適化しましたか?
    コンポーネントがページにどのように表示されるか、およびアセットをブラウザーに提供する方法の戦略は重要ですが、知覚されるパフォーマンスの役割も過小評価してはなりません。 このコンセプトは、待機の心理的側面を扱い、基本的に、何か他のことが起こっている間、顧客を忙しくしたり、従事させたりします。 そこで、知覚管理、先制的開始、早期完了、および許容度管理が機能します。

    それはどういう意味ですか? アセットをロードしている間、私たちは常にお客様の一歩先を行くように努めることができるので、バックグラウンドでかなり多くのことが起こっている間、経験は迅速に感じられます。 顧客の関心を維持するために、インジケーターをロードする代わりにスケルトン画面をテストし(実装デモ)、トランジション/アニメーションを追加し、基本的に最適化するものがないときにUXをごまかすことができます。

    The Art of UI Skeletonsのケーススタディで、Kumar McMillanは、動的リスト、テキスト、最終画面をシミュレートする方法、およびReactでスケルトン思考を検討する方法に関するいくつかのアイデアとテクニックを共有しています。

    ただし、注意してください。一部のテストでは、スケルトンスクリーンのパフォーマンスがすべてのメトリックで最悪であることが示されたため、スケルトンスクリーンはデプロイする前にテストする必要があります。

  3. レイアウトのずれや塗り直しを防ぎますか?
    知覚されるパフォーマンスの領域では、おそらくより破壊的なエクスペリエンスの1つは、再スケーリングされた画像やビデオ、Webフォント、挿入された広告、またはコンポーネントに実際のコンテンツを取り込む最近発見されたスクリプトによって引き起こされるレイアウトシフトまたはリフローです。 その結果、顧客は、読書エリアの上のレイアウトジャンプによって中断されるだけで記事を読み始める可能性があります。 経験はしばしば突然で非常に混乱します:そしてそれはおそらく再考される必要がある優先順位をロードする場合です。

    コミュニティは、リフローを回避するためのいくつかの手法と回避策を開発しました。 一般に、ユーザーの操作に応じて発生する場合を除いて、既存のコンテンツの上に新しいコンテンツを挿入しないことをお勧めします。 画像には常に幅と高さの属性を設定するため、最近のブラウザはボックスを割り当て、デフォルトでスペースを予約します(Firefox、Chrome)。

    画像と動画の両方で、SVGプレースホルダーを使用して、メディアが表示される表示ボックスを予約できます。つまり、アスペクト比を維持する必要がある場合にも、領域が適切に予約されます。 広告や動的コンテンツにプレースホルダーやフォールバック画像を使用したり、レイアウトスロットを事前に割り当てたりすることもできます。

    外部スクリプトを使用して画像を遅延読み込みする代わりに、ネイティブ遅延読み込みを使用するか、ネイティブ遅延読み込みがサポートされていない場合にのみ外部スクリプトを読み込むときにハイブリッド遅延読み込みを使用することを検討してください。

    上記のように、常にWebフォントの再描画をグループ化し、すべてのフォールバックフォントからすべてのWebフォントに一度に移行します。font-style-matcherを使用してフォント間の行の高さと間隔を調整することにより、切り替えが急激になりすぎないようにします。 。

    フォールバックフォントのフォントメトリックをオーバーライドしてWebフォントをエミュレートするには、@ font-face記述子を使用してフォントメトリックをオーバーライドできます(デモ、Chrome 87で有効)。 (ただし、複雑なフォントスタックでは調整が複雑になることに注意してください。)

    最近のCSSの場合、レイアウトが重要なCSSが各テンプレートのヘッダーにインライン化されていることを確認できます。 さらに、長いページの場合、垂直スクロールバーを追加すると、メインコンテンツが16px左にシフトします。 スクロールバーを早期に表示するために、 overflow-y: scrollを追加できますhtmlをスクロールして、最初のペイントでスクロールバーを適用します。 後者は、幅が変更されたときにスクロールバーが折り目の上のコンテンツのリフローのために重要なレイアウトシフトを引き起こす可能性があるため、役立ちます。 ただし、ほとんどの場合、Windowsのような非オーバーレイスクロールバーを備えたプラットフォームで発生するはずです。 しかし: position: stickyです。

    スクロール時にページの上部に固定または固定されたヘッダーを処理する場合は、コンテンツのプレースホルダー要素やmargin-topなど、ヘッダーがパインになったときにヘッダー用のスペースを予約します。 例外は、CLSに影響を与えてはならないCookie同意バナーですが、影響を与える場合もあります。実装によって異なります。 このTwitterスレッドには、いくつかの興味深い戦略とポイントがあります。

    さまざまな量のテキストが含まれる可能性のあるタブコンポーネントの場合、CSSグリッドスタックを使用してレイアウトのシフトを防ぐことができます。 各タブのコンテンツを同じグリッド領域に配置し、一度に1つを非表示にすることで、コンテナが常に大きい要素の高さを占めるようにすることができるため、レイアウトのずれは発生しません。

    ああ、そしてもちろん、リストの下にコンテンツ(フッターなど)がある場合は、無限のスクロールと「さらに読み込む」によってレイアウトがシフトする可能性があります。 CLSを改善するには、ユーザーがページのその部分にスクロールするに読み込まれるコンテンツ用に十分なスペースを確保し、コンテンツの読み込みによって押し下げられる可能性のあるページ下部のフッターまたはDOM要素を削除します。また、折り畳み下のコンテンツのデータと画像をプリフェッチして、ユーザーがそこまでスクロールするまでに、すでにそこにあるようにします。 react-windowのようなリスト仮想化ライブラリを使用して長いリストを最適化することもできます(ありがとう、Addy Osmani! )。

    リフローの影響を確実に抑えるには、Layout InstabilityAPIを使用してレイアウトの安定性を測定します。 これを使用すると、累積レイアウトシフト( CLS )スコアを計算し、それをテストの要件として含めることができるため、リグレッションが発生した場合はいつでも、それを追跡して修正できます。

    レイアウトシフトスコアを計算するために、ブラウザはビューポートのサイズと、レンダリングされた2つのフレーム間のビューポート内の不安定な要素の動きを調べます。 理想的には、スコアは0に近くなります。 CLSとは何か、CLSの測定方法については、MilicaMihajlijaとPhilipWaltonによるすばらしいガイドがあります。 これは、特にビジネスクリティカルなタスクの場合に、知覚されるパフォーマンスを測定および維持し、中断を回避するための良い出発点です。

    クイックヒント:DevToolsでレイアウトシフトの原因を見つけるには、パフォーマンスパネルの[エクスペリエンス]でレイアウトシフトを調べることができます。

    ボーナス:リフローとリペイントを減らしたい場合は、CharisTheodoulouのDOMリフロー/レイアウトスラッシングの最小化ガイドとPaulIrishのレイアウト/リフローを強制するもののリストとCSSTriggers.com、レイアウトをトリガーするCSSプロパティのリファレンステーブル、ペイントを確認してくださいと合成。

ネットワーキングとHTTP / 2

  1. OCSPステープリングは有効になっていますか?
    サーバーでOCSPステープリングを有効にすることで、TLSハンドシェイクを高速化できます。 オンライン証明書ステータスプロトコル(OCSP)は、証明書失効リスト(CRL)プロトコルの代替として作成されました。 両方のプロトコルは、SSL証明書が取り消されているかどうかを確認するために使用されます。

    ただし、OCSPプロトコルでは、ブラウザが証明書情報のリストをダウンロードして検索するのに時間を費やす必要がないため、ハンドシェイクに必要な時間が短縮されます。

  2. SSL証明書失効の影響を減らしましたか?
    「EV証明書のパフォーマンスコスト」に関する彼の記事で、Simon Hearneは、一般的な証明書の概要と、証明書の選択が全体的なパフォーマンスに与える影響について説明しています。

    Simonが書いているように、HTTPSの世界では、トラフィックを保護するために使用される証明書検証レベルにはいくつかの種類があります。

    • ドメイン検証(DV)は、証明書リクエスターがドメインを所有していることを検証します。
    • 組織検証(OV)は、組織がドメインを所有していることを検証します。
    • Extended Validation (EV)は、組織がドメインを所有していることを厳密な検証で検証します。

    これらの証明書はすべて、テクノロジーに関して同じであることに注意することが重要です。 それらは、それらの証明書で提供される情報とプロパティのみが異なります。

    EV証明書は、人間が証明書を確認してその有効性を確認する必要があるため、費用と時間がかかります。 一方、DV証明書は、多くの場合、無料で提供されます。たとえば、Let's Encryptによって、多くのホスティングプロバイダーやCDNに十分に統合されたオープンな自動認証局です。 実際、これを書いている時点では、ページの2.69%(Firefoxで開かれている)にすぎませんが、2億2500万を超えるWebサイト(PDF)に電力を供給しています。

    では、何が問題なのでしょうか。 問題は、 EV証明書が上記のOCSPステープリングを完全にサポートしていないことです。 ステープルを使用すると、サーバーは証明書が取り消されているかどうかを認証局に確認し、この情報を証明書に追加(「ステープル」)できます。ステープルを使用しないと、クライアントはすべての作業を行う必要があり、TLSネゴシエーション中に不要な要求が発生します。 。 接続が不十分な場合、パフォーマンスコストが顕著になる可能性があります(1000ミリ秒以上)。

    EV証明書は、Webパフォーマンスに最適な選択肢ではなく、DV証明書よりもパフォーマンスに大きな影響を与える可能性があります。 最適なWeb​​パフォーマンスを得るには、常にOCSPステープルDV証明書を提供してください。 また、EV証明書よりもはるかに安価で、取得の手間も少なくなります。 まあ、少なくともCRLiteが利用可能になるまでは。

    プレーン、圧縮、またはその両方の場合のサイトUDPデータグラムに沿ったハンドシェイクの数を示すグラフ
    圧縮の問題:非圧縮の証明書チェーンの40〜43%は大きすぎて、3つのUDPデータグラムの単一のQUICフライトに収まりません。 (画像クレジット:)ファストリー)(大プレビュー)

    :QUIC / HTTP / 3を使用している場合、TLS証明書チェーンがQUICハンドシェイクのバイト数を支配する1つの可変サイズのコンテンツであることに注意してください。 サイズは数百バイから10KB以上の間で異なります。

    したがって、TLS証明書を小さく保つことは、QUIC / HTTP / 3で非常に重要です。これは、証明書が大きいと複数のハンドシェイクが発生するためです。 また、証明書が圧縮されていることを確認する必要があります。そうしないと、証明書チェーンが大きすぎて1つのQUICフライトに収まりません。

    問題と解決策へのより多くの詳細とポインタを見つけることができます:

    • EV証明書は、Aaron PetersによるWebの速度を低下させ、信頼性を低下させます。
    • MattHobbsによるWebパフォーマンスに対するSSL証明書の失効の影響
    • SimonHearneによるEV証明書のパフォーマンスコスト
    • QUICハンドシェイクは高速であるために圧縮を必要としますか? パトリック・マクマヌス著。
  3. IPv6はもう採用しましたか?
    IPv4のスペースが不足しており、主要なモバイルネットワークがIPv6を急速に採用しているため(米国はIPv6の採用しきい値のほぼ50%に達しています)、将来に備えてDNSをIPv6に更新することをお勧めします。 ネットワーク全体でデュアルスタックサポートが提供されていることを確認してください。これにより、IPv6とIPv4を同時に実行できます。 結局のところ、IPv6には下位互換性がありません。 また、調査によると、IPv6は、近隣探索(NDP)とルートの最適化により、これらのWebサイトを10〜15%高速化しました。
  4. すべてのアセットがHTTP / 2(またはHTTP / 3)で実行されていることを確認してください。
    グーグルが過去数年にわたってより安全なHTTPSウェブを推進しているので、HTTP / 2環境への切り替えは間違いなく良い投資です。 実際、Web Almanacによると、すべてのリクエストの64%がすでにHTTP / 2を介して実行されています。

    HTTP / 2は完全ではなく、優先順位付けの問題があることを理解することが重要ですが、それは非常によくサポートされています。 そして、ほとんどの場合、あなたはそれを使ったほうがいいです。

    注意:HTTP / 2サーバープッシュはChromeから削除されているため、実装がサーバープッシュに依存している場合は、サーバープッシュを再検討する必要があります。 代わりに、Fastlyですでに実験として統合されているEarlyHintsを検討している可能性があります。

    まだHTTPで実行している場合、最も時間のかかるタスクは、最初にHTTPSに移行してから、ビルドプロセスを調整してHTTP / 2の多重化と並列化に対応することです。 HTTP / 2をGov.ukに導入することは、まさにそれを実行し、その過程でCORS、SRI、およびWPTを介して方法を見つけることに関する素晴らしいケーススタディです。 この記事の残りの部分では、HTTP / 2に切り替えているか、すでに切り替えていることを前提としています。

2016年1月2日から2020年10月1日までのデスクトップとモバイルの両方でのHTTP / 2リクエストの時系列を示すグラフ
Web Almanacによると、すべてのリクエストの64%は、正式な標準化からわずか4年後の2020年後半にHTTP / 2経由で処理されます。 (画像ソース:Webアルマナック)(大プレビュー)
  1. HTTP / 2を適切にデプロイします。
    繰り返しになりますが、HTTP / 2を介してアセットを提供することは、これまでのアセットの提供方法を​​部分的に見直すことで恩恵を受けることができます。 モジュールのパッケージ化と多数の小さなモジュールの並列ロードとの間の微妙なバランスを見つける必要があります。 結局のところ、それでも最善のリクエストはリクエストなしですが、目標は、アセットの迅速な最初の配信とキャッシングの間の微妙なバランスを見つけることです。

    一方では、インターフェース全体を多くの小さなモジュールに分割し、ビルドプロセスの一部としてそれらを圧縮して並列にロードするのではなく、アセットを完全に連結することを避けたい場合があります。 1つのファイルを変更しても、スタイルシート全体またはJavaScriptを再ダウンロードする必要はありません。 また、解析時間を最小限に抑え、個々のページのペイロードを低く抑えます。

    一方、パッケージングは​​依然として重要です。 多くの小さなスクリプトを使用すると、全体的な圧縮が低下し、キャッシュからオブジェクトを取得するコストが増加します。 大きなパッケージの圧縮は辞書の再利用の恩恵を受けますが、小さな個別のパッケージはそうではありません。 これに対処するための標準的な作業がありますが、今のところそれは遠いです。 第二に、ブラウザはまだそのようなワークフロー用に最適化されていません。 たとえば、Chromeはリソースの数に比例したプロセス間通信(IPC)をトリガーするため、数百のリソースを含めるとブラウザのランタイムコストが発生します。

    プログレッシブCSS読み込みを使用したHTMLコード
    HTTP / 2で最良の結果を得るには、ChromeのJake Archibaldが提案しているように、CSSを段階的にロードすることを検討してください。

    それでも、CSSを段階的にロードしてみることができます。 実際、インボディCSSはChromeのレンダリングをブロックしなくなりました。 ただし、優先順位付けの問題がいくつかあるため、それほど単純ではありませんが、試してみる価値があります。

    HTTP / 2接続の合体を回避することもできます。これにより、HTTP / 2の恩恵を受けながらドメインシャーディングを使用できますが、実際にこれを実現することは困難であり、一般に、これは良い習慣とは見なされません。 また、HTTP / 2とサブリソースの整合性が常に機能するとは限りません。

    何をすべきか? そうですね、HTTP / 2で実行している場合、 6〜10個のパッケージを送信することは、まともな妥協案のように思えます(そして、レガシーブラウザにとってはそれほど悪くはありません)。 実験と測定を行って、Webサイトの適切なバランスを見つけてください。

  2. すべてのアセットを単一のHTTP / 2接続で送信しますか?
    HTTP / 2の主な利点の1つは、単一の接続を介してアセットをネットワークに送信できることです。 ただし、CORSの問題が発生したり、 crossorigin属性を誤って設定したりすると、ブラウザが新しい接続を開くように強制されるなど、何か問題が発生した可能性があります。

    すべてのリクエストが単一のHTTP / 2接続を使用しているかどうか、または何かが正しく構成されていないかどうかを確認するには、DevTools→Networkの「ConnectionID」列を有効にします。 たとえば、ここでは、すべてのリクエストが同じ接続を共有します(286)—別の接続を開くmanifest.json(451)を除きます。

Chromeブラウザで開いているDevToolsのスクリーンショット
すべてのリクエストは同じHTTP / 2接続(286)を共有します—別の接続を開くmanifest.json(451)を除きます。 iamakulov経由。 (大プレビュー)
  1. サーバーとCDNはHTTP / 2をサポートしていますか?
    サーバーとCDNが異なれば(まだ)HTTP / 2のサポートも異なります。 CDN比較を使用してオプションを確認するか、サーバーのパフォーマンスとサポートが期待できる機能をすばやく調べます。

    HTTP / 2の優先順位(ビデオ)とHTTP / 2の優先順位付けのためのテストサーバーのサポートに関するPatMeenanの驚くべき研究を参照してください。 Patによると、Linux 4.9カーネル以降で確実に機能するようにHTTP / 2の優先順位付けを行うには、BBR輻輳制御を有効にし、 tcp_notsent_lowatを16KBに設定することをお勧めします(ありがとう、Yoav! )。 Andy Daviesは、ブラウザ、CDN、クラウドホスティングサービス全体でのHTTP / 2の優先順位付けについて同様の調査を行いました。

    その間、カーネルがTCP BBRをサポートしているかどうかを再確認し、可能であれば有効にします。 現在、Google Cloud Platform、Amazon Cloudfront、Linux(Ubuntuなど)で使用されています。

  2. HPACK圧縮を使用していますか?
    HTTP / 2を使用している場合は、サーバーがHTTP応答ヘッダーにHPACK圧縮を実装していることを再確認して、不要なオーバーヘッドを削減してください。 一部のHTTP / 2サーバーは、HPACKを例として、仕様を完全にサポートしていない場合があります。 H2specは、それをチェックするための優れた(技術的に詳細な場合)ツールです。 HPACKの圧縮アルゴリズムは非常に印象的で、機能します。
  3. サーバーのセキュリティが防弾であることを確認してください。
    HTTP / 2のすべてのブラウザ実装はTLSを介して実行されるため、セキュリティ警告やページ上の一部の要素が機能しないことを避けたいと思うでしょう。 セキュリティヘッダーが適切に設定されていることを再確認し、既知の脆弱性を排除して、HTTPS設定を確認します。

    また、すべての外部プラグインとトラッキングスクリプトがHTTPS経由で読み込まれていること、クロスサイトスクリプティングが不可能であること、HTTP Strict TransportSecurityヘッダーとContentSecurityPolicyヘッダーの両方が適切に設定されていることを確認してください。

  4. サーバーとCDNはHTTP / 3をサポートしていますか?
    HTTP / 2は、Webに多くの大幅なパフォーマンスの改善をもたらしましたが、改善の余地もかなりありました。特に、TCPのヘッドオブラインブロッキングは、パケット損失が大きい低速ネットワークで顕著でした。 HTTP / 3はこれらの問題を永久に解決しています(記事)。

    HTTP / 2の問題に対処するために、IETFは、Google、Akamaiなどとともに、最近HTTP / 3として標準化された新しいプロトコルに取り組んでいます。

    RobinMarxはHTTP / 3について非常によく説明しており、以下の説明は彼の説明に基づいています。 コアでは、HTTP / 3は機能の点でHTTP / 2と非常に似ていますが、内部的には非常に異なった動作をします。 HTTP / 3は、より高速なハンドシェイク、より優れた暗号化、より信頼性の高い独立したストリーム、より優れた暗号化とフロー制御など、多くの改善を提供します。 注目すべき違いは、HTTP / 3がトランスポート層としてQUICを使用し、QUICパケットがTCPではなくUDPダイアグラムの上にカプセル化されていることです。

    QUICはTLS1.3をプロトコルに完全に統合しますが、TCPでは最上位に階層化されています。 通常のTCPスタックでは、TCPとTLSが独自のハンドシェイクを実行する必要があるため、オーバーヘッドのラウンドトリップ時間が数回ありますが、QUICを使用すると、両方を組み合わせて1回のラウンドトリップで完了することができます。 TLS 1.3では、結果として生じる接続の暗号化キーを設定できるため、2番目以降の接続では、「0-RTT」と呼ばれる最初のラウンドトリップでアプリケーション層データをすでに送受信できます。

    また、HTTP / 2のヘッダー圧縮アルゴリズムは、優先順位付けシステムとともに完全に書き直されました。 さらに、QUICは、各QUICパケットのヘッダーにある接続IDを介したWi-Fiからセルラーネットワークへの接続移行をサポートします。 ほとんどの実装はカーネル空間ではなくユーザー空間で行われるため(TCPで行われるように)、プロトコルが将来進化することを期待する必要があります。

    それはすべて大きな違いを生むでしょうか? おそらくそうです。特にモバイルでの読み込み時間だけでなく、エンドユーザーへのアセットの提供方法にも影響を与えます。 HTTP / 2では、複数のリクエストが接続を共有しますが、HTTP / 3リクエストでも接続を共有しますが、独立してストリーミングするため、ドロップされたパケットはすべてのリクエストに影響を与えることはなく、1つのストリームにのみ影響します。

    つまり、1つの大きなJavaScriptバンドルでは、1つのストリームが一時停止するとアセットの処理が遅くなりますが、複数のファイルが並列にストリーミングされる場合(HTTP / 3)の影響はそれほど大きくありません。 したがって、パッケージングは​​依然として重要です。

    HTTP / 3はまだ進行中です。 Chrome、Firefox、Safariにはすでに実装があります。 一部のCDNはすでにQUICとHTTP / 3をサポートしています。 2020年後半に、ChromeはHTTP / 3とIETFQUICの導入を開始しました。実際、すべてのGoogleサービス(Google Analytics、YouTubeなど)はすでにHTTP / 3で実行されています。 LiteSpeedWebサーバーはHTTP / 3をサポートしていますが、Apache、nginx、IISのいずれもまだサポートしていませんが、2021年に急速に変更される可能性があります。

    結論:サーバーとCDNでHTTP / 3を使用するオプションがある場合は、そうすることをお勧めします。 主な利点は、特に待ち時間の長い接続で、複数のオブジェクトを同時にフェッチすることから得られます。 その分野で行われた研究はあまりないので、まだはっきりとはわかりませんが、最初の結果は非常に有望です。

    プロトコルの詳細と利点について詳しく知りたい場合は、次の点を確認してください。

    • HTTP / 3 Explained、HTTP / 3とQUICプロトコルを文書化するための共同作業。 さまざまな言語で利用でき、PDFとしても利用できます。
    • DanielStenbergによるHTTP / 3によるWebパフォーマンスのレベルアップ。
    • Robin Marxを使用したQUICのアカデミックガイドでは、QUICおよびHTTP / 3プロトコルの基本概念を紹介し、HTTP / 3がヘッドオブラインブロッキングと接続移行を処理する方法、およびHTTP / 3が常緑になるように設計されている方法を説明しています(ありがとう、 Simon !)。
    • サーバーがHTTP3Check.netのHTTP / 3で実行されているかどうかを確認できます。

テストとモニタリング

  1. 監査ワークフローを最適化しましたか?
    大したことではないように聞こえるかもしれませんが、適切な設定を指先で行うことで、テストにかかる時間を大幅に節約できる可能性があります。 WebPageTestのパブリックインスタンスにテストを送信するには、TimKadlecのAlfredWorkflow forWebPageTestを使用することを検討してください。 実際、WebPageTestには多くのあいまいな機能があるため、時間をかけてWebPageTestウォーターフォールビューチャートを読み取る方法と、WebPageTest接続ビューチャートを読み取ってパフォーマンスの問題をより迅速に診断および解決する方法を学習してください。

    また、GoogleスプレッドシートからWebPageTestを駆動し、アクセシビリティ、パフォーマンス、SEOスコアをLighthouse CIを使用してTravisセットアップに組み込むか、Webpackに直接組み込むこともできます。

    最近リリースされたAutoWebPerfをご覧ください。これは、複数のソースからパフォーマンスデータを自動的に収集できるモジュラーツールです。 たとえば、重要なページに毎日テストを設定して、CrUX APIからフィールドデータをキャプチャし、PageSpeedInsightsからLighthouseレポートからラボデータをキャプチャすることができます。

    また、何かをすばやくデバッグする必要があるが、ビルドプロセスが非常に遅いように思われる場合は、「空白の削除とシンボルのマングリングは、複雑なコード変換ではなく、ほとんどのJavaScriptの縮小コードのサイズ縮小の95%を占めることに注意してください。圧縮を無効にするだけで、Uglifyのビルドが3〜4倍高速化されます。」

レビューが必要であり、チェックが正常に解決されるまでマージがブロックされることを示すGitHubのプルリクエスト通知のスクリーンショット
アクセシビリティ、パフォーマンス、SEOスコアをLighthouse CIを使用してTravisセットアップに統合すると、貢献しているすべての開発者にとって新機能のパフォーマンスへの影響が浮き彫りになります。 (画像ソース)(大きなプレビュー)
  1. プロキシブラウザとレガシーブラウザでテストしましたか?
    ChromeとFirefoxでのテストだけでは不十分です。 プロキシブラウザとレガシーブラウザでWebサイトがどのように機能するかを調べます。 たとえば、UCBrowserとOperaMiniは、アジアで大きな市場シェアを持っています(アジアでは最大35%)。 将来の大きな驚きを避けるために、関心のある国の平均インターネット速度を測定します。 ネットワークスロットリングでテストし、高DPIデバイスをエミュレートします。 BrowserStackは、リモートの実際のデバイスでのテストに最適であり、オフィス内の少なくともいくつかの実際のデバイスで補完することもできます。それだけの価値があります。
  1. 404ページのパフォーマンスをテストしましたか?
    通常、404ページに関しては二度と考えません。 結局のところ、クライアントがサーバーに存在しないページを要求すると、サーバーは404ステータスコードと関連する404ページで応答します。 そんなに多くはありませんね。

    404応答の重要な側面は、ブラウザーに送信される実際の応答本文のサイズです。 Matt Hobbsによる404ページの調査によると、404応答の大部分は、ファビコンの欠落、WordPressアップロード要求、壊れたJavaScript要求、マニフェストファイル、CSSおよびフォントファイルからのものです。 クライアントが存在しないアセットをリクエストするたびに、404レスポンスを受け取ります。多くの場合、そのレスポンスは膨大です。

    404ページのキャッシュ戦略を調べて最適化してください。 私たちの目標は、ブラウザがHTML応答を期待する場合にのみ、ブラウザにHTMLを提供し、他のすべての応答に対して小さなエラーペイロードを返すことです。 Mattによると、「CDNをオリジンの前に配置すると、404ページの応答をCDNにキャッシュする機会があります。これがないと、404ページをヒットするとDoS攻撃ベクトルとして使用される可能性があるため便利です。 CDNにキャッシュされたバージョンで応答させるのではなく、オリジンサーバーにすべての404要求に応答するように強制します。」

    404エラーはパフォーマンスに悪影響を与える可能性があるだけでなく、トラフィックにコストがかかる可能性があるため、Lighthouseテストスイートに404エラーページを含めて、そのスコアを経時的に追跡することをお勧めします。

  2. GDPR同意プロンプトのパフォーマンスをテストしましたか?
    GDPRとCCPAの時代には、EUの顧客が追跡をオプトインまたはオプトアウトするためのオプションを提供するために、サードパーティに依存することが一般的になっています。 ただし、他のサードパーティスクリプトと同様に、それらのパフォーマンスは、パフォーマンスの取り組み全体に非常に大きな影響を与える可能性があります。

    もちろん、実際の同意によって全体的なパフォーマンスに対するスクリプトの影響が変わる可能性が高いため、Boris Schapiraが指摘したように、いくつかの異なるWebパフォーマンスプロファイルを調査することをお勧めします。

    • 同意は完全に拒否されました、
    • 同意は部分的に拒否されました、
    • 同意は完全に与えられました。
    • ユーザーが同意プロンプトに対応していません(またはプロンプトがコンテンツブロッカーによってブロックされました)、

    通常、Cookieの同意プロンプトはCLSに影響を与えるべきではありませんが、影響を与える場合もあるため、無料のオープンソースオプションであるOsanoまたはcookie-consent-boxの使用を検討してください。

    一般に、マウスイベントの水平方向または垂直方向のオフセットを決定し、アンカーに対してポップアップを正しく配置する必要があるため、ポップアップのパフォーマンスを調べる価値があります。 Noam Rosenthalは、Webパフォーマンスのケーススタディ:ウィキペディアのページプレビュー(ビデオおよび議事録としても利用可能)の記事でウィキメディアチームの学習を共有しています。

  3. パフォーマンス診断CSSを保持していますか?
    パフォーマンスの低いコードがデプロイされていることを確認するためにあらゆる種類のチェックを含めることができますが、簡単に解決できるいくつかの簡単な成果をすばやく把握しておくと便利なことがよくあります。 そのために、Tim Kadlecの優れたパフォーマンス診断CSS(遅延読み込み画像、サイズなし画像、レガシー形式の画像、同期スクリプトを強調表示するHarryRobertsのスニペットに触発されたもの)を使用できます。

    たとえば、折り目の上の画像が遅延ロードされないようにすることができます。 必要に応じてスニペットをカスタマイズできます。たとえば、使用されていないWebフォントを強調表示したり、アイコンフォントを検出したりできます。 デバッグ中に間違いが表示されるようにするため、または現在のプロジェクトを非常に迅速に監査するための優れた小さなツール。

    /* Performance Diagnostics CSS */ /* via Harry Roberts. https://twitter.com/csswizardry/status/1346477682544951296 */ img[loading=lazy] { outline: 10px solid red; }
  1. アクセシビリティへの影響をテストしましたか?
    ブラウザがページの読み込みを開始すると、DOMが構築され、スクリーンリーダーのような支援技術が実行されている場合は、アクセシビリティツリーも作成されます。 次に、スクリーンリーダーは、ユーザー補助ツリーにクエリを実行して情報を取得し、ユーザーが利用できるようにする必要があります。デフォルトの場合もあれば、オンデマンドの場合もあります。 そして時々それは時間がかかります。

    インタラクティブへの高速時間について話すとき、通常、ユーザーがリンクやボタンをクリックまたはタップすることによってページを操作できる時間の指標を意味します。 スクリーンリーダーでは、コンテキストが少し異なります。 その場合、インタラクティブへの高速時間とは、スクリーンリーダーが特定のページのナビゲーションをアナウンスでき、スクリーンリーダーのユーザーが実際にキーボードを押して操作できるようになるまでにどれだけの時間が経過するかを意味します。

    Leonie Watsonは、アクセシビリティパフォーマンス、特に読み込みが遅いことがスクリーンリーダーのアナウンスの遅延に与える影響について目を見張るような話をしました。 スクリーンリーダーは、ペースの速いアナウンスと迅速なナビゲーションに慣れているため、目の見えるユーザーよりも忍耐力が低い可能性があります。

    大きなページとJavaScriptを使用したDOM操作により、スクリーンリーダーのアナウンスが遅れます。 スクリーンリーダーは文字通りすべてのプラットフォーム(Jaws、NVDA、Voiceover、Narrator、Orca)で利用できるため、注意とテストを使用できる、かなり未踏の領域です。

  2. 継続的な監視が設定されていますか?
    WebPagetestのプライベートインスタンスを持つことは、迅速で無制限のテストに常に役立ちます。 ただし、自動アラート機能を備えた継続的な監視ツール(Sitespeed、Calibre、SpeedCurveなど)を使用すると、パフォーマンスの詳細を把握できます。 独自のユーザータイミングマークを設定して、ビジネス固有のメトリックを測定および監視します。 また、自動パフォーマンス回帰アラートを追加して、時間の経過に伴う変化を監視することを検討してください。

    RUMソリューションを使用して、時間の経過に伴うパフォーマンスの変化を監視することを検討してください。 自動化された単体テストのような負荷テストツールの場合、スクリプトAPIでk6を使用できます。 また、SpeedTracker、Lighthouse、Calibreも調べてください。

クイックウィン

このリストは非常に包括的であり、すべての最適化を完了するにはかなりの時間がかかる場合があります。 それで、もしあなたが大幅な改善を得るのにたった1時間しかなかったとしたら、あなたはどうしますか? それをすべて17個のぶら下がっている果物に煮詰めましょう。 明らかに、開始する前と終了したら、3Gおよびケーブル接続での最大のコンテンツフルペイントとインタラクティブまでの時間などの結果を測定します。

  1. 実世界の経験を測定し、適切な目標を設定します。 最速の競合他社よりも少なくとも20%速くなることを目指してください。 最大のコンテンツフルペイント<2.5秒、最初の入力遅延<100ミリ秒、低速3Gでのインタラクティブまでの時間<5秒、繰り返しの訪問、TTI <2秒以内にとどまります。 少なくとも最初の満足のいくペイントとインタラクティブまでの時間のために最適化します。
  2. Squoosh、mozjpeg、guetzli、pingo、SVGOMGを使用して画像を最適化し、画像CDNを使用してAVIF / WebPを提供します。
  3. メインテンプレート用の重要なCSSを準備し、各テンプレートの<head>にインライン化します。 CSS / JSの場合、最大の重要なファイルサイズバジェット内で動作します。 170KB gzip圧縮(0.7MB解凍)。
  4. スクリプトのトリミング、最適化、延期、遅延読み込み。 バンドラーの構成に投資して、冗長性を取り除き、軽量の代替案を確認します。
  5. 静的アセットは常にセルフホストし、サードパーティのアセットは常にセルフホストすることを好みます。 サードパーティのスクリプトの影響を制限します。 ファサードを使用し、インタラクションでウィジェットをロードし、ちらつき防止スニペットに注意してください。
  6. フレームワークを選択するときは選択してください。 シングルページアプリケーションの場合、重要なページを特定して静的に提供するか、少なくとも事前にレンダリングし、コンポーネントレベルでプログレッシブハイドレーションを使用し、インタラクションでモジュールをインポートします。
  7. クライアント側のレンダリングだけでは、パフォーマンスを向上させることはできません。 ページがあまり変更されていない場合は事前レンダリングし、可能であればフレームワークの起動を延期します。 可能であれば、ストリーミングサーバー側レンダリングを使用してください。
  8. <script type="module">およびmodule / nomoduleパターンを持つレガシーブラウザにのみレガシーコードを提供します。
  9. CSSルールを再グループ化して、本体のCSSをテストしてみてください。
  10. リソースヒントを追加して、より高速なdns-lookuppreconnectprefetchpreloadprerender
  11. Webフォントをサブセット化して非同期にロードし、CSSのfont-displayを利用して最初のレンダリングを高速化します。
  12. HTTPキャッシュヘッダーとセキュリティヘッダーが正しく設定されていることを確認してください。
  13. サーバーでBrotli圧縮を有効にします。 (それが不可能な場合は、少なくともGzip圧縮が有効になっていることを確認してください。)
  14. サーバーがLinuxカーネルバージョン4.9以降で実行されている限り、TCPBBR輻輳を有効にします。
  15. 可能であれば、OCSPステープリングとIPv6を有効にします。 常にOCSPステープルDV証明書を提供します。
  16. HTTP / 2のHPACK圧縮を有効にし、利用可能な場合はHTTP / 3に移動します。
  17. フォント、スタイル、JavaScript、画像などのアセットをServiceWorkerキャッシュにキャッシュします。

チェックリストのダウンロード(PDF、Apple Pages)

このチェックリストを念頭に置いて、あらゆる種類のフロントエンドパフォーマンスプロジェクトに備える必要があります。 チェックリストの印刷可能なPDFと、編集可能なApple Pagesドキュメントをダウンロードして、ニーズに合わせてチェックリストをカスタマイズしてください。

  • チェックリストPDFをダウンロード(PDF、166 KB)
  • Apple Pagesのチェックリストをダウンロードする(.pages、275 KB)
  • MS Wordのチェックリストをダウンロードする(.docx、151 KB)

別の方法が必要な場合は、Dan Rublicによるフロントエンドチェックリスト、Jon Yablonskiによる「Designer'sWeb Performance Checklist」、およびFrontendChecklistを確認することもできます。

オフウィーゴー!

最適化の一部は、作業や予算の範囲を超えているか、処理する必要のあるレガシーコードを考えるとやり過ぎかもしれません。 それはいいです! このチェックリストを一般的な(そしてできれば包括的な)ガイドとして使用し、コンテキストに適用される問題の独自のリストを作成してください。 しかし、最も重要なことは、最適化する前に、独自のプロジェクトをテストおよび測定して問題を特定することです。 みんな、2021年にハッピーパフォーマンスを達成!


Guy Podjarny、Yoav Weiss、Addy Osmani、Artem Denysov、Denys Mishunov、Ilya Pukhalski、Jeremy Wagner、Colin Bendell、Mark Zeman、Patrick Meenan、Leonardo Losoviz、Andy Davies、Rachel Andrew、Anselm Hannemann、Barry Pollard、 Hamann、Gideon Pyzer、Andy Davies、Maria Prosvernina、Tim Kadlec、Rey Bango、Matthias Ott、Peter Bowyer、Phil Walton、Mariana Peralta、Pepijn Senders、Mark Nottingham、Jean Pierre Vincent、Philipp Tellis、Ryan Townsend、Ingrid Bergman、Mohamed Hussain SH、JacobGroß、Tim Swalling、Bob Visser、Kev Adamson、Adir Amsalem、Aleksey Kulikov、Rodney Rehm、およびこの記事をレビューしてくれた素晴らしいコミュニティ、そしてパフォーマンス最適化の作業から学んだ技術と教訓を誰もが使用できるように共有している素晴らしいコミュニティ。 あなたは本当に粉砕しています!