UIパフォーマンスの最適化
1)「速い」とカウントするもの"
TTFB (time to first byte)-高速なサーバー/CDN応答。
LCP(最大のコンテンツフルペイント)-「メイン」コンテンツがすぐに登場しました。
INP (Interaction to Next Paint)-インタラクション中の応答性。
CLS(累積レイアウトシフト)-インターフェイスジッタがない。
TTI (Time to Interactive)-すべてがすでに応答している場合。
推奨基準点:LCP ≤ 2。5s、 INP ≤ 200ms、 CLS ≤ 0。1(実質のユーザーの75パーセンタイルのために)。
2)プロセス: 測定→ボトルネックを見つける→予算を修正
1.測定:RUM(実際のユーザー、国/ネットワーク/デバイス別パーセンタイル)+合成(灯台/ブラウザ)。
2.検索:パフォーマンスプロファイラ(長いタスク>50ms、レイアウトスラッシング、余分なレンダー)。
3.修正:予算(JS/CSS/フォント、 LCP/INPの重量)とCIの「赤い線」。
3)ネットワークおよび資源のローディング
3.1 HTTPと優先順位
HTTP/2/3、 Brotli圧縮を有効にします。
'critical domains';'dns-prefetch'をセカンダリドメインに。
'preload'はクリティカルリソース(ヒーローイメージ、メインフォント)のために使われます。
'fetchpriority=」high/low」と'priority'のヒントがサポートされています。
3.2キャッシング
ファイルハッシュで静的:'Cache-Control: public、 max-age=31536000、 immutable'。
HTML-CDNを介して短いTTL+stale-while-revalidate。
オフライン/リピート訪問のためのETag/Last-ModifiedおよびService Worker。
4)コード: less、 latter、 「flatter」
4.1アセンブリ
木の揺れ、minify(木。ч.dead-code-elim)。
ルート/ウィジェットによるコード分割、動的インポート。
基本的なバンドル(moment→Intl/Day)で「グローバル」の重いパケットを避けます。js)。
4.2 HTMLレンダリングと配信
SSR/ISR/ストリーミング:フレームワークとメインコンテンツを最初に与えます。
部分的な水分補給:水分補給はインタラクティブな領域のみです。
すべての非クリティカル:'<script type=「module」 defer>'を無効にします。
4.3反応特異性(Reactを使用した場合)
"反応しなさい。lazyウィジェットのためのlazy'+'Suspense'。
'startTransition'と'useDeferredValue'は重いフィルタ/ルックアップのために使われます。
RSC (Server Components)-サーバ計算、クライアントのJS未満。
(zustand/redux)のセレクタ:コンポーネントをフラグメントに署名します。スタック全体ではありません。
5)レンダリングと状態: ここで「遅くなります」
5.1レレンダーの分離
大きなコンポーネント、memoize ('memo'、 'useMemo'、 'useCallback')をクラッシュします。
リストキーは安定しています。不必要にpropsに新しい関数/オブジェクトを作成しないでください。
頻繁にデータを変更するための「グローバル」コンテキストを避ける-セレクターまたはイベントバスを使用します。
5.2仮想化と大きなリスト
シート/テーブル→仮想化(レンダリングウィンドウ)
バックプレッシャーによるページネーション/無限スクロール(100kラインを一度にロードしない)。
ビューポート外の重いウィジェットの遅延初期化。
5.3レイアウト&ペイント
content-visibility: auto;隠しパーティション(ブラウザは見えないものをレンダリングしません)。
includeと'include-intrinsic-size'を指定します。
頻繁なレイアウト読み取りエントリ(レイアウトスラッシュ)を避けます。グループの測定。
will-change use dosed(それ以外の場合は余分なメモリ/レイヤー)。
6)イメージおよびグラフィック
フォーマット:AVIF/WebP (PNG/JPEGのフォールバック)。
レスポンシブアプローチ:'srcset'+'sizes'、網膜のための密度ベース。
'loading=」lazy」'はヒーローイメージではありません。priority/preload-LCP候補のみ。
固定サイズのプレースホルダ→CLSジャンプなし。
キャンバス/チャート:計算のためのオフスクリーンキャンバスとWeb Worker;リドローを撃ち殺してる。
7)フォントとテキスト
多くのスタイルの代わりに1つまたは2つの可変フォント。
'font-display: swap'/'optional'、基本スタイルのプリロード。
'size-adjust'はフォントを変更する際の「ジャンプ」を減らします。
同様の指標を持つローカルフォールバックフォント。
8) CSSとアニメーション
重要なCSSインライン(<14-20 kB)、残り-延期されます。
未使用のスタイル(Purge/CSSTree)を削除します。
アニメーション、可能であれば、変換/不透明度;リスペクト'prefers-reduced-motion'
深いカスケードやブラストセレクターは避けてください。
9) Webワーカー、フローと重いタスク
すべてのCPUヘビー-ワーカー(解析、ソート、集約、ML)。
ストリーミングAPI ('ReadableStream'、 'fetch' with stream)を長時間の応答のために使用します。
応答性を維持するために'requestIdleCallback '/microtasksを介してタスクをチャンクに分割します。
10)レイアウトの安定性(CLS)
LCP要素(イメージ/ウィジェット)のスペースを予約します。
固定サイズなしでバナー/リボンを挿入しないでください。
非対称的なチューリップ/トースト-コンテンツを移動しないでください。レイヤー/ポータルを使用します。
11)スニペットの例
クリティカルフォントとLCPイメージ
html
<link rel="preload" href="/fonts/Inter. var. woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" as="image" href="/hero. avif" imagesrcset="/hero. avif 1x, /hero@2x. avif 2x" fetchpriority="high">
遅延と安全なウィジェットの初期化
js const Widget = React. lazy(() => import('./Widget'));
function Section() {
const inView = useInViewport('#sec');
return <div id="sec">{inView? <React. Suspense fallback={null}><Widget/></React. Suspense>: null}</div>;
}
レイアウトの安定化
css
.hero {
content-visibility: auto;
contain: layout paint;
contain-intrinsic-size: 720px 320px ;/LCP reserve/
}
12)回帰制御と予算
バンドル予算:合計JS ≤ N kB、 CSS ≤ M kB、初期チャンク≤ K kB。
CIのWebバイタル(エミュレート)+RUMアラート(パーセンタイル上)。
バンドル解析:PRでのsource-map-explorer/analyzer。
コンポーネントの性能ベンチマーク(10k要素のレンダリング、反応時間)。
13)アンチパターン
読み込み「all at all at all at all」:グラフ、エディタ、マップを最初の画面に表示します。
巨大なグローバル状態→カスケードレンダリング。
画像「srcset/sizes」なしで、目的のサイズの2-4 ×。
メインスレッド上の長い同期ループ。
'ouline: none'と最適化なしのカスタムトリック-レンダリングインジケータを干渉します。
'top/left'によるアニメーション(レイアウトを壊してrefluxを呼び出します)。
14)スクリーンチェックリスト
- LCP ≤ 2。3G/mobileトラフィック上の5 s、 CLS ≤ 0。1のINP ≤ 200ms
- 重要なリソース:プリロード/優先順位;残りはdefer/lazy
- バンドル:コード分割、追加の依存関係なし
- リスト/テーブルの仮想化、重いウィジェットの遅延初期化
- 画像:AVIF/WebP、' srcset/sizes'、 'loading=」lazy」'
- フォント:変数+'font-display'、プリロードのみ
- CSS:クリティカルなインライン、パージ、'content-visibility'および'contain'
- 重いコンピューティングのための労働者/アイドル
- 予算とWeb-Vitalsがダッシュボード/アラートに接続されている
15)実施計画(3つの反復)
イテレーション1-クイックウィン(1-2週間)
Brotli/HTTP-2/3、 CDNを有効にします。重要なCSSとLCPリソースのプリロード。
重いウィジェットを動的インポートに移動します。
画像→AVIF/WebP+'srcset'。フォント:'font-display: swap'。
イテレーション2-構造改善(3〜4週間)
ルート別コード分割、バンドル解析、「重い」リブの除去。
仮想化、コンテンツの可視性、include-intrinsic-sizeを一覧表示します。
SSR/ストリーミング/アイランド(関連する場合)を実装します。
Web-VitalsのRUM、 CIの予算。
反復3-スケールと堅牢性(連続)
Workers/offscreen canvas、 butching計算、startTransition/deferredValue。
定期的なPERF監査、回帰自動ダイジェスト、チームトレーニング。
16) ミニFAQ
モバイルで最もスピードアップするものは何ですか?
元のJS、 SSR/ストリーミングを削減し、LCPイメージを最適化します。
SSRは常に必要ですか?
いいえ、そうではありません。ページが動的にインタラクティブでキャッシュされていない場合、islands/partial hydrationの方が良いかもしれません。
INPが「光」バンドルで悪いのはなぜですか?
おそらくメインスレッド上の長いタスク(ソート、グラフィックス)-それらをWorkerに持ち込み、タスクを分割します。
合計
Fast UIは、ネットワークの優先順位とキャッシュ、小さくて遅いバンドル、予測可能なジャンプ以外のレンダリング、経済的なイメージとフォント、そして一定の現実世界のメトリック制御などの分野の集まりです。予算を入力し、チェックを自動化し、すべてのステップでスピードについて考えるようにチームに教えます。このようにして、インターフェイスは今日でも1年でも高速に維持されます。