Ele.me、複数ページのプログレッシブ ウェブアプリで読み込み時間を改善

Ele.me は、中国本土で最大の料理の注文と配達を行う会社です。中国全土の 200 以上の都市から 2 億 6, 000 万人の登録ユーザーにサービスを提供し、130 万件以上のレストラン リスティングを掲載しています。ユーザーの 99% がモバイルで料理を注文するなかで、Ele.me はモバイルウェブのエクスペリエンスを改善し、不安定な接続でも高速で信頼性の高い接続を実現しながら、マルチページ アプリのコア技術モデルを活用して運用ニーズに対応することにしました。

  • すべての事前キャッシュされたページで、読み込み時間が 11.6% 短縮されました
  • 全ページで読み込み時間が平均 6.35% 短縮されました。
  • 3G ネットワーク上での初回読み込み時に、一貫してインタラクティブにするまでの時間が 4.93 秒に短縮されました。

ele.me PWA のリリース後、読み込み時間が大幅に短縮され、モバイルウェブ エクスペリエンスが中国で最速の食品予約サイトの 1 つへと変貌を遂げました。

Ele.me PWA プロダクト マネージャー Spencer Yang 氏

マルチページ アプリとシングルページ アプリのどちらかを選択する

マルチページ アプリ(MPA)では、ユーザーが移動するすべてのルートが、必要な関連するスクリプトとスタイルとともに、ページの完全なリクエストをトリガーします。これは、すべてのルート ナビゲーションでそのルートに関連するコンテンツとデータに対してのみフェッチがトリガーされ、UI はクライアント アプリで実行される JavaScript コードによって構築されるシングルページ アプリ(SPA)モデルとは対照的です。

近年の Ele.me の急速な成長に伴い、メインの https://ele.me ドメインでそれぞれマイクロサービスの実行を担う個別のビジネス ユニットが成長しました。Ele.me のチームは、こうした個々のサービスの分離には、各チームが独自のサービスを運用、維持するマルチページ アプリ(MPA)モデルが最適であると結論付けました。

MPA への PRPL の適用

PRPL パターン(重要なリソースのプリロード、初期ルートの事前キャッシュ、残りのルートの事前キャッシュ、残りの Lazy-load ルート)は、インタラクティビティに要する時間を短縮すること、ネットワーク ラウンド トリップを削減するためのキャッシュの最大化に特に重点を置いて、PWA の構造を導くための一連のレールを提供します。PRPL は SPA で十分にテストされていますが、実際に MPA にどのように適用するかは明確ではありません。Ele.me は、MPA を PWA として再構築する際に、PRPL の考え方を採用することにしました。そのためには、ユーザーがページに移動したときに、必要に応じて <link rel="preload"> を含めるか、ブラウザのプリローダーが追加のヒントを必要とせずに作業できるように、十分な浅いレベルでスクリプトを表示することで、そのページの重要なリソースをプリロードします。また、ブラウザでサポートされている場合は常に Service Worker をインストールすることで、PWA を段階的に拡張します。これにより、他のトップレベル ナビゲーション ルートを取得して事前キャッシュしておくことで、ユーザーが PWA 内をクリックしたときに、読み込みとレンダリングが高速化されます。MPA 内の各ページは独自のルートであるため、最初のルートのレンダリングを高速化することは、各ルートのクリティカル レンダリング パスを最適化するベスト プラクティスを実装することと同じです。この変更により、すべてのページの全体の読み込み時間が平均 6.35% 短縮されました。

遷移スケルトン画面への提供をできるだけ早く行う

Ele.me は、スケルトン画面のアイデアを UX に応用したいと考えました。スケルトン スクリーンとは、ユーザーがボタンやリンクをタップするたびにページを可能な限り迅速に反応させる方法です。つまり、ユーザーを新しいページに移行し、コンテンツが使用可能になったときにコンテンツをそのページに読み込みます。これは、PWA の認識されるパフォーマンスを向上させるうえでも重要です。ただし、MPA 内の各ページは独自の初期ルートであるため、ナビゲーションごとに必要な読み込み、解析、評価作業をすべてやり直す必要があります。

これを回避するために、Ele.me は実際の UI コンポーネントとしてスケルトン画面を作成し、Vue.js のサーバーサイド レンダリング スタックを使用して Vue コンポーネントを構築し、HTML テンプレートに挿入する前に文字列にプリレンダリングしました。これにより、スケルトン画面を直接レンダリングし、ページ間を移動する際に、より滑らかな遷移を行うことができます。


ページ遷移中のスケルトン画面
ページ遷移中のスケルトン画面
ページ遷移後にページが完全にレンダリングされます
ページ遷移後にページが完全にレンダリングされる

Service Worker による共有リソースのキャッシュ

ユーザーが PWA をブラウジングすると複数のルートが読み込まれます。このようなルートをネットワークから何度も読み込むのは無駄です。この問題に対処するために、Ele.me はユーザーが最も重視する重要なルートを分析し、これらの重要なルートの依存関係を収集する webpack プラグインを作成して、ユーザーのクライアント ブラウザに Service Worker をインストールする際に、これらのルートを事前にキャッシュに保存しました。これらの重要なルートには、PWA の一般的な UI シェルを形成する JavaScript、CSS、画像が含まれます。

重要とみなされても重要ではないルートは、ユーザーが PWA 内を移動し続ける代わりに、実行時に Service Worker によって段階的にキャッシュされます。これにより、Ele.me はすべてのネットワーク条件下で、キャッシュから直接 PWA をユーザーに提供できます。その結果、すべての事前キャッシュされたページ全体で読み込み時間が 11.6% 短縮されました。

参考資料