このケーススタディでは、PageSpeed Insights(PSI)、Chrome DevTools、scheduler.yield
API などの Google ツールを活用して、Trendyol で使用される React の INP をデバッグおよび改善するワークフローをステップごとに説明します。
e コマース ウェブサイトに不可欠な 2 つのコンポーネントは、商品リスティング ページ(PLP)と商品の詳細ページ(PDP)です。e コマースのトラフィックは多くの場合、メール キャンペーン、ソーシャル メディア、広告など、商品リスティング ページから発生します。そのため、購入までの時間を短縮するように、PLP のエクスペリエンスを慎重に設計することが重要です。成功を収めるには、ユーザー エクスペリエンスの品質を優先することが不可欠です。Milliseconds Make Millions などの研究出版物では、オンラインでの消費者の購買意欲やブランドとの関わりにウェブ パフォーマンスが与える大きな影響がすでに明らかになっています。
Trendyol は、約 3,000 万人の顧客と 24 万人の販売者を抱える e コマース プラットフォームです。これにより、当社はトルコ初の企業となり、評価額は 100 億ドルを超え、世界トップクラスの e コマース プラットフォームの一つとなりました。
コンテンツの柔軟性を維持し、古いバージョンの React と連携しながら、可能な限り最高のユーザー エクスペリエンスを提供するという目標を達成するために、Trendyol は改善の主要な指標として Interaction to Next Paint(INP)に焦点を当てました。このケーススタディでは、Trendyol が PLP の INP を改善し、INP を 50% 削減し、検索結果のビジネス指標が 1% 上昇した過程について説明します。
Trendyol の INP 調査プロセス
INP は、ユーザー入力に対するウェブサイトの応答性を測定するものです。優れた INP は、ブラウザがすべてのユーザー入力に迅速かつ確実に応答し、ページを再描画できることを意味します。これは、優れたユーザー エクスペリエンスの重要な要素です。
Trendyol が PLP の INP を改善する取り組みは、改善を行う前に、ユーザー エクスペリエンスの徹底的な分析から始まりました。PSI レポートによると、次の図に示すように、PLP の実際のユーザー エクスペリエンスの INP はモバイルで 963 ミリ秒でした。
優れた応答性を確保するため、サイト所有者は INP が 200 ミリ秒未満または 200 ミリ秒を目指す必要があります。これは、その時点で Trendyol の INP が「低い」範囲にあったことを意味します。
PSI は、Chrome ユーザー エクスペリエンス レポート(CrUX)に含まれるページのフィールド データと、詳細なラボ診断データの両方を提供しています。ラボのデータによると、Lighthouse の JavaScript 実行時間監査では、search-result-v2
スクリプトがメインスレッドを占有する時間が、ページ上の他のスクリプトよりも長いことが示唆されています。
実際のボトルネックを特定するため、Chrome DevTools のパフォーマンス パネルを使用して PLP エクスペリエンスをトラブルシューティングし、問題の原因を特定しました。Chrome DevTools で、CPU 速度を 4 倍に低下させながらモバイルのパフォーマンスをエミュレートしたところ、メインスレッドで 700 ~ 900 ミリ秒のタスクが発生することが明らかになりました。メインスレッドが他のタスクで 50 ミリ秒以上占有されている場合、ユーザー入力にタイムリーに応答できず、ユーザー エクスペリエンスが低下する可能性があります。
最も長いタスクは、React コンポーネント内の検索結果スクリプトに対する Intersection Observer API コールバックによって発生しました。この時点で、ブラウザがより優先度の高い作業(ユーザーの操作を含む)に応答する機会を増やすために、この長いタスクを小さなチャンクに分割する取り組みを開始しました。
Intersection Observer コールバック内で React の再レンダリングをトリガーする setState
オペレーションを使用すると、コストが高くなり、ローエンド デバイスではメインスレッドを長時間占有しすぎると問題が生じることがわかりました。
デベロッパーがタスクを小さなタスクに分割するために使用した手法の 1 つに、setTimeout
があります。この手法を使用して、setState
呼び出しの実行を別のタスクで延期しました。setTimeout
を使用すると JavaScript の実行を延期できますが、優先度を制御することはできません。これにより、メインスレッドに譲った後のスクリプト実行の継続を保証するために、scheduler.yield
オリジン トライアルに参加しました。
/*
* Yielding method using scheduler.yield, falling back to setTimeout:
*/
async function yieldToMain() {
if('scheduler' in window && 'yield' in scheduler) {
return await scheduler.yield();
}
return new Promise(resolve => {
setTimeout(resolve, 0);
});
}
/*
* Yielding to the main thread before changing the state of the component:
*/
const observer = new IntersectionObserver((entries) => {
entries.forEach(handleIntersection);
const maxNumberOfEntries = Math.max(...this.intersectingEntries);
if (Number.isFinite(maxNumberOfEntries)) {
await this.yieldToMain();
this.setState({ count: maxNumberOfEntries });
}
}, { threshold: 0.5 });
この yiling メソッドを PLP コードに追加すると、主要な長いタスクが一連の小さなタスクに分割され、ユーザー操作やその後のレンダリング作業など、優先度の高い作業をより早く実行できるようになり、INP が改善されました。
なお、Trendyol は PuzzleJs フレームワークを使用して、React v16.9.0 を使用するマイクロフロントエンド アーキテクチャを実装します。React 18 でも同じパフォーマンスを達成できますが、さまざまな理由により、現時点では Trendyol はアップグレードできません。
ビジネス上の成果
実装した INP の改善の影響を測定するために、A/B テストを実施して、ビジネス指標への影響を確認しました。全体として、PLP の変更により、INP が 50% 減少し、ユーザー セッションあたりのリスティングページから商品の詳細ページへのクリック率が 1% 向上するなど、大幅な改善が実現しました。次の図では、時間の経過とともに PLP で INP がどのように改善されたかを確認できます。
おわりに
INP の最適化は複雑で反復的なプロセスですが、明確なワークフローによって簡単に行うことができます。ウェブサイトの INP のデバッグと改善を行うシンプルな方法は、独自のフィールド データを収集しているかどうかによって異なります。まだ使用していない場合は、PSI と Lighthouse を使用することをおすすめします。問題のあるページを特定したら、DevTools を使用してさらに深く掘り下げて問題を再現できます。
ブラウザが緊急の作業を行う機会を増やすためにときどきメインスレッドに譲ることで、ウェブサイトの応答性が向上し、顧客の利便性が向上します。scheduler.yield()
などの新しいスケジューリング API を使用すると、このタスクが簡単になります。
本作業に協力してくれた Google の Jeremy Wagner、Barry Pollard、Hussein Djirdeh、Trendyol のエンジニアリング チームに感謝します。