ウェブアプリのパフォーマンスに関するベストプラクティス
ユーザーに好まれるアプリを構築するには、パフォーマンスに優れたアプリにすることが不可欠です。開発プロセス全体を通してパフォーマンスをモニタリングしてください。レイテンシを表す主な指標には、最初のフレームまでの時間(TTFF)と使用準備完了(RTU)の2つがあり、後者は描画完了までの時間(TTFD)とも呼ばれます。ここでは、アプリのパフォーマンスを向上させる一般的なベストプラクティスをいくつか取り上げます。

ネイティブのSplashScreen APIの使用
アプリの起動時のパフォーマンスは、ユーザーエクスペリエンスに影響を与えます。ユーザーは、アプリを起動時したらすぐに何らかの画面が表示されることを期待しています。その表示までの速さを表す指標が、TTFF(最初のフレームまでの時間)です。Vega向けReact NativeのネイティブSplashScreen機能は、画像アセットを使用してアプリ固有のスプラッシュ画面を表示します。アプリを起動すると、ユーザーにこの画面がすぐに表示されます。アプリでは、JavaScriptベースのスプラッシュスクリーンをレンダリングすることに時間を割く必要なく、コンテンツの読み込みとネットワーク呼び出しに集中できます。スプラッシュ画面には、一連のアニメーション画像によるアニメーション効果を含めることができます。
この主なパフォーマンス指標(KPI)は、manifest.tomlファイルで指定されたメインコンポーネントが起動してから、最初のフレームをレンダリングするまでにかかる時間として測定します。

SplashScreenManagerを使用すると、アプリの次の画面に進むまでの画面用に、静的グラフィックスまたはアニメーショングラフィックスを作成できます。SplashScreenは、アプリのパッケージング時に、アプリの起動にデバイスが使用するアセットをバンドルします。SplashScreenを使用すると、アプリ起動時の複雑さがいくらか解消され、アプリで最初のフレームの準備ができるまで起動画面が表示されます。
TTFD(描画完了までの時間)マーカーの実装
Vegaアプリは、アプリライフサイクルの各段階で特定のパフォーマンスマーカーの基準を満たす必要があります。マーカーの1つがTTFDです(前の画像を参照)。アプリが正常に読み込まれ、ユーザーとの対話が可能になったら、TTFDマーカーを満たすようにアプリを最適化します。アプリプロセスが開始される前のクールスタート時も、アプリプロセスが既に実行中であるウォームスタート時と同じパフォーマンスマーカーを満たす必要があります。ウェブアプリでは、ウェブアプリのコンテンツが完全に読み込まれたときに、onLoadコールバックでこのマーカーを実装する必要があります。
ウェブアプリを起動して読み込んだ後、useReportFullyDrawn()メソッドを呼び出します。ラッパーにはonLoadイベントがあり、アプリが起動して準備が整ったときにトリガーされます。また、ウォーム起動中にバックグラウンドからフォアグラウンドに移動したときも、reportFullyDrawn()メソッドを呼び出します。
次のサンプルコードでは、コールドスタート(onLoad)とウォームスタート(keplerAppState)の両方の処理でuseReportFullyDrawn()を呼び出しています。
import { useReportFullyDrawn } from '@amazon-devices/kepler-performance-api';
import React, { useEffect, useState, useRef } from 'react';
import {VegaAppStateChange, useAddVegaAppStateListenerCallback, useGetCurrentVegaAppStateCallback} from '@amazon-devices/react-native-kepler';
...
...
export const App = () => {
const reportFullyDrawnCallback = useReportFullyDrawn();
const getCurrentVegaAppStateCallback = useGetCurrentVegaAppStateCallback();
const addVegaAppStateListenerCallback = useAddVegaAppStateListenerCallback();
const [appState, setAppState] = useState(getCurrentVegaAppStateCallback);
// useEffectフックを使用して、初回レンダリング後、状態が
// フォアグラウンドに変わるときに、描画完了の報告が実行されるようにします。
// アプリで追加の非同期処理を実行していて、
// その処理が完了するまで描画完了にならない場合は、
// 処理の完了状態を依存配列に渡し、フック内で
// 状態を確認します。
useEffect(() => {
const changeSubscription = addVegaAppStateListenerCallback(
'change',
handleAppStateChange
);
}, [reportFullyDrawnCallback]);
const handleAppStateChange = (nextAppState: any) => {
if (
appState.match(/inactive|background/) &&
nextAppState === 'active'
) {
reportFullyDrawnCallback();
}
setAppState(nextAppState);
};
...
...
return (
<View style={styles.sectionContainer}>
<WebView
.
.
.
onLoad={(event) => {
console.log("onLoad url: ", event.nativeEvent.url)
// スプラッシュ画面を非表示にしてコンテンツをレンダリングします。
SplashScreenManager.hideAsync(your.package.name).catch((e) => {
console.error("スプラッシュ画面を非表示にするときにエラーが発生しました:" , e) });
// 実際のページが読み込まれた場合にのみ描画完了を報告します。
if("https://mywebapp.com/home" === event.nativeEvent.url)
{
reportFullyDrawnCallback();
}
}}
/>
</View>
);
};
詳細については、How to implement reportFullyDrawn marker for WebView Apps(英語のみ)を参照してください。
ネットワークリクエストの最適化
ウェブアプリの起動パフォーマンスを向上させるには、ネットワークリクエストを最適化する必要があります。HTTPリクエストを最小限に抑えることで起動パフォーマンスを向上させることができます。そのためには、可能な場合はCSSファイルとJavaScriptファイルを結合すること、スプライト画像を使用すること、外部のサードパーティへの依存関係を減らすことが効果的です。また、GzipやBrotliを使用してアセット圧縮を有効にすると、HTML、CSS、JavaScriptなどのテキストベースリソースのペイロードサイズを大幅に削減できます。ただし、画像ファイルは通常既に圧縮されているため、この利点は適用されません。
<!-- 非効率的、すべてのケースで必要とは限りません -->
<script src="utils.js"></script>
<script src="api.js"></script>
<scriptsrc="main.js"></script>
<!-- 最適化済み - 論理的に結合できる場合 -->
<script src="app.bundle.js" defer></script>
HTTP/2やHTTP/3などの最新のHTTPプロトコルを活用することも効果的です。これらのプロトコルは多重化をサポートしており、1つの接続で複数の要求を同時に送信することでオーバーヘッドを最小限に抑えます。クライアント側のリダイレクトを減らすことも、レイテンシの改善に役立ちます。リダイレクトがあると、そのたびに余分なラウンドトリップが追加され、ページの読み込みが遅くなります。
サーバーの応答時間の短縮
高速で応答性の高いユーザーエクスペリエンスを提供するためには、サーバーの応答時間を最適化することが重要です。最も効果的な戦略の1つは、コンテンツ配信ネットワーク(CDN)を使用することです。CDNは、画像、JavaScript、CSSファイルなどの静的アセットを、地理的にユーザーに近いエッジロケーションから提供し、レイテンシを削減します。最初のバイトまでの時間(TTFB)を短縮すると、パフォーマンスが大幅に向上する可能性があります。これは、データベースクエリの改善、ミドルウェアのオーバーヘッドの削減、サーバーロジックの最適化など、バックエンド処理を最適化することで達成できます。
APIの効率性も関係があります。API呼び出しの数を最小限に抑え、適切な場合は結合し、リクエストの重複を回避すると、ネットワークのオーバーヘッドを減らすことができます。コンテンツ配信を高速化するには、サーバーサイドレンダリング(SSR)や静的サイト生成(SSG)の使用を検討してください。これらのウェブテクノロジーは、サーバー上でHTMLを事前にレンダリングしてページの読み込みを高速化し、最初のコンテンツの描画(FCP)を改善します。FCTとは、ブラウザがコンテンツの最初の部分をレンダリングするまでにかかる時間です。また、最も重要なコンテンツを最優先するために、遅延読み込みのテクニックを使用して、重要でないデータや補助的なデータの読み込みを遅らせることもできます。
レンダリングとJavaScriptの実行の最適化
高速で応答性の高いウェブアプリを作成するには、レンダリングとJavaScriptの実行を最適化します。重要な方針の1つは、ページの読み込み中に負荷の高い計算や不要なロジックによってメインJavaScriptスレッドがブロックされるのを防ぐことです。メインスレッドがブロックされると、レンダリングが遅延してドロップフレームが発生し、ユーザーエクスペリエンスに悪影響が及ぶ可能性があります。
スレッドがブロックされないようにするには、JavaScriptを軽量に保ち、最初の読み込み時は必要なコードのみを実行します。入力イベント処理に必要なコードのみを実行することもできます。入力ハンドラーは、フレームの完了を妨げたり、不要なレイアウト処理を追加したりする可能性があるため、アプリの滑らかさに影響するパフォーマンスの問題を引き起こすことがあります。そこで、ハンドラーはデバウンスすることをお勧めします。つまり、イベントの値を保存して、次のrequestAnimationFrameコールバックでスタイルの変更を処理します。
ページのレンダリングがブロックされるのを防ぐために、すぐに必要とされないスクリプトは、async属性またはdefer属性を使用して非同期で読み込みます。これにより、レンダリングをブロックするJavaScriptの影響が軽減されます。
// JavaScriptを非同期で読み込みます。
<script src="analytics.js" defer></script>
// 必要時に動的にデータ/JavaScriptをインポートします。
import('./data.js').then(initData);
コード分割を使用すると、JavaScriptモジュールの動的な読み込みが可能になり、ページや機能ごとに必要なスクリプトだけを読み込むことができます。よりスムーズなアニメーションを実現し、視覚的なパフォーマンスを改善するには、transformとwill-changeのようなCSSプロパティを使用してアクセラレーションを有効にします。CSSを通じたGPUアクセラレーションは、レンダリングをGPUにオフロードするために役立ちます。これらの戦略により、ウェブアプリの体感的なパフォーマンスと実際のパフォーマンスが向上します。
JavaScriptを最適化するもう1つの方法として、ウェブワーカーがあります。これにより、スクリプトをバックグラウンドで実行できます。詳細については、ウェブアプリのウェブワーカーに関するベストプラクティスを参照してください。
リソースのキャッシュ
キャッシュを使用すると、ウェブアプリのパフォーマンスと応答性が高まります。クライアント側のキャッシュを有効にするには、JavaScriptファイル、CSS、データ、画像などのリソースに対して適切なCache-Controlヘッダーを設定します。キャッシュにより、ウェブアプリでこれらのアセットを保存して再利用することも可能になり、何度もダウンロードする必要がなくなります。また、CDNキャッシュを利用すると、ユーザーの近くにあるエッジロケーションから静的コンテンツが提供され、読み込み時間が大幅に短縮される可能性があります。クライアントキャッシュとCDNキャッシュを組み合わせることで、開発者はサーバーの負荷を軽減し、レイテンシを減らし、よりスムーズなエクスペリエンスをエンドユーザーに提供できます。
スクロールパフォーマンスの向上
アプリのスクロールパフォーマンスを向上させるには、考慮すべき点がいくつかあります。まず、offsetTopやscrollHeightなどのレイアウトプロパティには、スクロールイベントハンドラーから頻繁にアクセスしたり変更を加えたりしないようにします。これらの変更を行うと、レイアウトは毎回再計算されるため、パフォーマンスに影響します。スロットリングやデバウンスのメカニズムを使用して、スクロールイベントの処理頻度を制限することもできます。強制的なリフローを防ぐために、スクロールリスナーの内部では、レイアウトの同期的な読み込みや書き込みを避けることをお勧めします。
ページ上のすべてのコンテンツやスクロールリスト全体をレンダリングするのではなく、表示されている要素や必要な要素のみをレンダリングします。スムーズなスクロールを実現するには、GPUアクセラレーション対応のCSSプロパティを使用することも効果的です。たとえば、CPU負荷の高いtop、left、widthなどのプロパティの代わりに、transformを使用します。
Chrome DevToolsの [レンダリング] タブには、スクロール中に低速な描画や重複する描画が発生しているレイヤーを視覚的に強調表示する機能があります。このツールを使用すると、パフォーマンスのボトルネックを特定し、スクロール動作を最適化できます。
ウェブアプリのKPIの測定
Vegaには、主要なパフォーマンス指標を高いレベルで測定するVega App KPI Visualizerツールが用意されています。このツールを使用すると、最初のフレームまでの時間(TTFF)、描画完了までの時間(TTFD)、スクロールの滑らかさ、ビデオの滑らかさの指標を測定できます。詳細については、アプリのKPIの測定を参照してください。
より詳細で低レベルな視点からウェブアプリのパフォーマンスを確認するには、Chrome DevTools(CDT)を使用します。Chromeツールに含まれている [パフォーマンス] タブ、[ネットワーク] タブ、Lighthouseを使用すると、ベンチマークを監査したり、ウェブアプリのホットスポット(HTML/JS/CSS/画像)を特定したりでき、アプリのパフォーマンスを改善するために役立ちます。現在、LightHouseはVegaで機能しませんが、ウェブアプリをデスクトップ版Chromeで直接読み込み、適切なネットワーク制限とCPU制限を適用してデバッグできます。
関連トピック
Last updated: 2026年2月6日

