y4shiro / uma-card-deck-tools

uma-card-deck-tools.vercel.app
0 stars 0 forks source link

モーダルのカード表示が重いのでチューニング #42

Closed y4shiro closed 1 year ago

y4shiro commented 1 year ago

カードスロットをクリックしてモーダルを開く際、クリックしてモーダルを開くまでに結構な時間が掛かっている(500 ~ 800ms) モーダル自体のアニメーションに 200 ms ほど掛かっているものの、それを差し引いても長いので改善したい また、モーダル開閉以外にカード表示のフィルタ切替時も時間が掛かっているので、こちらも併せて改善したい

計測した値

改善前の値を記載する

モーダル開閉

500 ~ 800 ms

レアリティ切り替え

ALL -> SSR : 200 ~ 238 ms SSR -> ALL : 380 ~ 438 ms

Todo

y4shiro commented 1 year ago

レンダリングが重い原因調査

思い当たる節が 2 点ほどある

前者から調査する

Card コンポーネント

next/image の blur エフェクトが重いので、これ切るだけでかなり改善する

一旦 blur を削除した状態でコミット後、スマホでの挙動見てみると、 スマホでの挙動が大分改善され、モーダルを開いた時やフィルタの切替時もかなり軽快になった

lazyload が適切に実行されていない

next/image はデフォルトで lazyload が有効になっており、viewport 外の要素は画像読み込みが行われない様になっている

https://nextjs.org/docs/api-reference/next/image#loading

The loading behavior of the image. Defaults to lazy.

現在の Modal コンポーネントを調査してみると、Card コンポーネントの殆ど全ての読み込み / レンダリングが行われている この現象は、next/image が生成する要素の高さ (height) がレンダリング開始直後に 0 となっているのが原因 これにより、map で展開している Card コンポーネントの 9 割程が viewport 内に収まってしまい、lazyload が意味を成さなくなっている

これを解決するため、レンダリング開始時に viewport 外にある Card コンポーネントに関しては代替コンポーネントを表示し、viewport に近づいた場合に本物の Card コンポーネントに差し替えて表示する方法を取ることにした

y4shiro commented 1 year ago

Card コンポーネントの blur エフェクトを削除

これは next/image の blur 要素を削除するだけ

y4shiro commented 1 year ago

SelectableCard のレンダリングを Intersection Observer で抑制

今回のロジックとしては、SelectableCard コンポーネントが viewport 外の場合はダミーや placeholder に該当する代替コンポーネントを表示し、viewport に近づいた場合は本物の SelectableCard コンポーネントに差し替えるというものにした

また、今回は Intersection Observer で SelectableCard コンポーネントが viewport に近づいたかを判定することにした

React で Intersection Observer を扱うライブラリを採用した

最終的に次のようなコードを書いた

https://github.com/y4shiro/uma-card-deck-tools/blob/2fad47013c76553d821fe331614a3a1dffec4161/src/features/Support/CardDeck/CardModal/MultipleObserver/index.tsx#L1-L31

MultipleObserver コンポーネントの実装により、Modal コンポーネントを開いた場合にレンダリングされる Card コンポーネント (next/image) の数が 200 個から 30 個程に抑制され、モーダル開閉やフィルタ絞り込みの処理時間も短縮された

y4shiro commented 1 year ago

動作確認

Chrome Devtools のパフォーマンス機能で、モーダル開閉やフィルタ絞り込み時の所要時間を計測した

モーダル開閉

改善前 500 ~ 800 ms 改善後 300 ~ 400 ms

フィルタ絞り込み

ALL -> SSR 改善前 200 ~ 238 ms 改善後 100 ms

SSR -> ALL 改善前 380 ~ 438 ms 改善後 248 ms

y4shiro commented 1 year ago

merge したので close します