最近、WeChat 小プログラムの冷起動時間の最適化に取り組んでおり、小プログラム公式ドキュメントを参照したところ、非常に詳細に書かれていることがわかりました。ここでは、開発者が重点的に注意すべき部分を記録・整理します。
起動の定義#
「ユーザーが小プログラムを開く」を起点とし、「小プログラムのホームページのレンダリングが完了する」まで。
小プログラムの「ホームページのレンダリングが完了する」の合図は、最初のページの Page.onReady
イベントの発火です。起動プロセスの違いにより、小プログラムで定義される「ホームページのレンダリングが完了する」は、ブラウザの DOMContentLoaded
または load
イベントとは異なります。
起動プロセスと時間の影響#
WeChat 小プログラムを開くからホームページが表示されるまで、以下のプロセスを経る必要があります:
各プロセスは直列ではなく、できるだけ並列で行われ、単純に段階ごとの合計起動時間を計算することはできません。
リソースの準備#
小プログラムに関連する情報の準備
ユーザーが初めて小プログラムにアクセスする、小プログラムのバージョンが更新される、または長期間使用されていない小プログラムを使用する場合、WeChat クライアントは小プログラムのアイコン、ニックネーム、バージョン、設定、権限などの基本情報を WeChat バックエンドから取得する必要があります。これにより、小プログラムのバージョン管理、権限制御、検証などが行われます。
情報のリアルタイム性を確保しながら、起動時間への影響をできるだけ抑えるため、これらの情報はローカルにキャッシュされ、一定のメカニズムによって更新されます。
小プログラムのバージョンをリリースすると、同期リクエストが増加し、平均的な起動時間が増加する可能性があります。そのため、開発者はバージョンのリリースを適切に計画することをお勧めします。
実行環境の準備
小プログラムの実行環境には、小プログラムプロセス、クライアントのネイティブシステムコンポーネントや UI 要素(ナビゲーションバー、タブバーなど)、レンダリングページに使用される WebView
コンテナ、開発者の JavaScript
コードの実行環境、小プログラムの基礎ライブラリなどが含まれます。
一部の環境(JavaScript エンジン、小プログラムの基礎ライブラリなど)は、小プログラムコードの実行前に準備が完了する必要があり、他の環境は起動プロセス中に並行して実行されます。
起動環境の準備による起動時間への影響をできるだけ抑えるため、WeChat クライアントはユーザーの使用シーンとデバイスリソースの使用状況に基づいて、一定の戦略に従って小プログラムの起動前に実行環境の一部を事前にプリロードします。
コードパッケージの準備
ユーザーが初めて小プログラムにアクセスするか、小プログラムのバージョンが更新される場合、WeChat バックエンドからユーザーがアクセスするページに基づいてコードパッケージのアドレスを取得し、CDN から小プログラムのコードパッケージをダウンロードし、コードパッケージを検証します。小プログラムのページが異なるサブパッケージに属している場合や使用しているプラグインが異なる場合、一度の起動で複数のコードパッケージやプラグインパッケージをダウンロードする必要があります。
起動プロセス以外でも、ページ遷移、プリロード、サブパッケージの非同期化などのプロセスでもコードパッケージのダウンロードがトリガされます。
ユーザーができるだけ新しいバージョンにアクセスできるようにするため、起動時間への影響をできるだけ抑えるため、小プログラムのコードパッケージはローカルにキャッシュされ、一定のメカニズムによって更新されます。
また、コードパッケージのダウンロード時間を短縮するために、WeChat は コードパッケージの圧縮、増分更新、より効率的なネットワークプロトコル、CDN のプリコネクション、コードパッケージの再利用 などの方法を採用しています。
ユーザーエクスペリエンスへの影響を考慮して、プラットフォームは 1 つの小プログラムのコードパッケージのサイズ制限を 2M に設定しています。起動速度を確保するため、開発者は起動時に使用するコードパッケージのサイズをできるだけ制御する必要があります。具体的な方法については、「コードパッケージのサイズ最適化」を参照してください。
小プログラムコードの注入(ロジックレイヤー)#
小プログラムの起動時には、コードパッケージから小プログラムの設定とコードを読み取り、JavaScript
エンジンに注入する必要があります。** メインパッケージのコード注入プロセスでは、小プログラムの App.onLaunch
と App.onShow
ライフサイクルがトリガされます。** 小プログラムがプラグインや拡張ライブラリを使用している場合、開発者のコードを注入する前に、対応するプラグインや拡張ライブラリのコードが先に注入されます。
一部のプラットフォームでは、WeChat クライアントは V8 エンジンの Code Caching 技術を使用して、コンパイル結果をキャッシュし、初回以外の注入時のコンパイル時間を短縮しています。
「ホームページのレンダリング」にはロジックレイヤーから送信されるデータが必要ですが、小プログラムのコード注入にかかる時間が長いと、「ホームページのレンダリング」の開始時間が遅れる可能性があります。開発者は「コード注入の最適化」セクションを参考にして最適化を行うことをお勧めします。
小プログラムコードの注入(ビューレイヤー)#
開発者の WXSS
と WXML
は、ビューレイヤーに注入されるため、ページのレンダリングに必要なページ構造とスタイル情報が含まれます。
ビューレイヤーとロジックレイヤーの小プログラムコードの注入は並行して行われます。
「ホームページのレンダリング」にはビューレイヤーのページ構造とスタイル情報が必要ですが、小プログラムのコード注入にかかる時間が長いと、ロジックレイヤーからビューレイヤーにデータが到達するまでの時間が遅れ、ホームページのレンダリング時間が影響を受けます。
ビューレイヤーで生成された JS コードは直接変更できませんが、「要求に応じて注入」や未使用のカスタムコンポーネントの削除などの方法を使用して、この部分の時間を短縮することができます。
ホームページ(初回)のレンダリング#
ロジックレイヤーの小プログラムコードの注入が完了した後、小プログラムフレームワークはユーザーがアクセスしたページに基づいてページコンポーネントツリーを初期化し、ビューレイヤーに初期データを送信し、ホームページの Page.onLoad
、Page.onShow
ライフサイクルを順番にトリガします。
ビューレイヤーのコード注入が完了し、ロジックレイヤーから受け取った初期データとビューレイヤーから得られたページ構造とスタイル情報を組み合わせて、小プログラムフレームワークは小プログラムのホームページをレンダリングし、小プログラムの初期画面を表示し、ホームページの Page.onReady
イベントをトリガします。これにより、小プログラムの起動プロセスが完了します。
ホームページのレンダリング時間は起動プロセスの最後のステップであり、小プログラムの起動時間に直接影響します。時間のかかるかどうかは、ページの構造の複雑さやレンダリングに参加するカスタムコンポーネントの数によって異なります。開発者は「初回画面のレンダリングの最適化」セクションを参考にして最適化を行うことをお勧めします。
「要求に応じて注入」を有効にしている場合、一部のコンポーネントコードの注入はこの段階で遅延されるため、ステージの時間が増加しますが、総合的な時間は通常減少します。
初回画面の表示#
「ホームページのレンダリング」が完了すると、小プログラムの起動プロセスが完了し、ローディングが消えます。この時点で通常、ユーザーはすぐに初回画面を見ることができるはずです。ネットワークリクエストに依存する場合は、setData によるページの更新が行われた後に表示されます。ユーザーエクスペリエンスを最適化するために、白い画面を避けるために「スケルトンスクリーン」を先に表示することもできます。
非同期の setData による描画トリガーの初回画面表示は、起動時間の統計に含まれない場合がありますが、ページのコンテンツがユーザーに表示されるまでの時間が遅れ、ユーザーエクスペリエンスに影響を与えます。開発者は「初回画面のレンダリングの最適化」セクションを参考にして最適化を行うことをお勧めします。
最適化戦略#
小プログラムの起動プロセスでは、コードパッケージの準備、小プログラムコードの注入、およびホームページのレンダリングにかかる時間は、小プログラム自体に関連しています。開発者は以下の点を最適化することができます:
- コードパッケージのサイズ最適化
- サブパッケージの読み込み、独立サブパッケージ、サブパッケージの非同期化
- 通常のサブパッケージの読み込みでは相互参照できないため、サブパッケージの非同期化を使用して解決できます
- 独立したサブパッケージはメインパッケージをダウンロードする必要がないため、メインパッケージに依存することもできません
- 不要なグローバルカスタムコンポーネントやプラグインを避ける
- コードパッケージ内のリソースファイルの制御:画像は CDN で読み込む
- 不要なコードとリソースを適時にクリーンアップ:コードの静的依存関係分析を使用する
- サブパッケージの読み込み、独立サブパッケージ、サブパッケージの非同期化
- コード注入の最適化
- 要求に応じて注入とタイミングによる注入:不要なグローバルカスタムコンポーネントやプラグインを避ける
- 起動時の同期 API 呼び出しを減らす:小プログラムの初期化コード(Page、App の定義以外の内容)と
App.onLaunch, App.onShow, Page.onLoad, Page.onShow
のいくつかのライフサイクルで、現在の JS スレッドをブロックしないようにする - 起動時の複雑な演算を減らす:上記と同様
- 初回画面のレンダリングの最適化
- 要求に応じて注入とタイミングによる注入を有効にする:初期化する必要のあるコンポーネントの数を減らす
- 初期レンダリングキャッシュを有効にする:2 回目以降の起動時にロジックレイヤーの初期化プロセスをスキップする
- 未使用のカスタムコンポーネントを避ける
- 初回画面のデータを簡素化する:ビューレイヤーのレンダリングに関係のないデータは、できるだけ
data
に入れないようにする - 初回画面のデータリクエストを事前に行う:
Page.onLoad
やそれより前のタイミングでネットワークリクエストを発行する - リクエストデータをローカルにキャッシュする:
wx.setStorage
、wx.getStorage
- スケルトンスクリーン
- その他の最適化の提案
- バージョンのリリース頻度を制御する