MUIで作成したテーブルコンポーネントのパフォーマンス改善

こんにちは。関西開発拠点でマネーフォワード クラウド連結会計(以下、クラウド連結会計)のフロントエンドエンジニアをやっています、上野(@uenoY4)です。
今回はクラウド連結会計のフロントエンドでテーブルのパフォーマンス改善を行ったので紹介させてください。

クラウド連結会計の技術構成

クラウド連結会計のフロントエンドは以下の構成で実装しています。

実装するコンポーネントは全て MUI から提供されているものをベースに使用して実装しています。

課題

今回、表示項目が多く、動きのついたテーブルを実装することになり、いつもの通り MUI が提供している Table コンポーネントをベースとして、実装を進めました。
表示項目が多いこともあり、試しに向こう 3 年後に想定されるマックスのデータ数( 500 行 × 200 列くらいのテーブル)を表示させようとしたところテーブルを含むコンポーネントの初期描画に 12 秒ほどかかってしまいました。

以下 React Profiler のキャプチャです。

具体的な課題は以下でした。

  • 初期描画が遅い。
  • table haeder をクリックすることで table cell の開閉を実装したが、クリックしてから開閉されるまで遅い。
  • カテゴリーで表示対象を絞り込んでいるが、クリックされてから絞り込まれたデータが表示されるまで時間がかかる。

以下の gif が実際の動作です。

className で実装

テーブルに表示するデータを増やしたことで課題が出てきました。
実際 React Profiler を使って計測しても、テーブルを使用しているコンポーネントの描画に時間がかかっていることは明確でした。
そして MUI を使った際のパフォーマンスに関しては、 MUI の公式にある Performance tradeoffs の通り、 className を渡してコンポーネントを描画した方が styled-components や MUI が提供する sx props を使用した実装よりもパフォーマンスが良く、以下の記述の通り、簡単な解決策として、多くの項目をレンダリングする場合は各項目に className を使用して実装することもできると書かれています。

We believe that for most use cases it’s fast enough, but there are simple workarounds when performance becomes critical. For instance, when rendering a list with many items, you can use a CSS child selector to have a single “style injection” point (using d. for the wrapper and a. for each item).

なのでテーブルの実装を MUI ではなく、 className を使用して再実装したところ、先ほど 12 秒弱かかっていた初期描画が 5 秒弱まで減らすことができました。

まだ 5 秒近くかかっていますが、この改修で初期描画が遅い問題は緩和されました。
しかし、table cell の開閉、カテゴリーをクリックした際の絞り込みは思っていたより改善が見られませんでした。

以下 gif は className を使って実装した画面です。

react-virtuso で実装

さらに MUI の公式ドキュメントをみていると Virtualized table という記載がありました。

In the following example, we demonstrate how to use react-virtualized with the Table component. It renders 200 rows and can easily handle more. Virtualization helps with performance issues.

上記の通り、仮想化することでパフォーマンスの改善ができるとのことなので、仮想化のライブラリを調べ、 TypeScript 製の react-virtuoso を使用してみました。
その結果、CSS Modules でも 5 秒弱かかっていたコンポーネントの表示が 300 ms以下で表示することができました。(約 94 % 減)

また、 table cell の開閉、カテゴリーをクリックした際の絞り込みについてもなんのストレスもなく、機能するようにようになりました。

以下 gif は react virtuso で実装した画面です。

今回の改善を通して

今回、改善に取り掛かった当初、色々なブログに飛びついて実装を試したりしていました。
ただ、最終的に採用した改善策はどちらも公式ドキュメントに書かれている方法でした。
ブログの方が手っ取り早そうに見えて飛びついてしまうのですが、近道に見えて遠回りをしているかもしれないです。
まずは公式ドキュメントをしっかり読み込んで対応策が書かれていないか、 GitHub に issue が上がっていないかなど一次情報をきちんと探すことは大切だと改めて痛感しました。
MUI を使用して描画に時間がかかっている方がいれば是非参考にして頂けると嬉しいです。

終わりに

クラウド連結会計では一緒に開発する仲間を大募集しています!
カジュアル面談や選考に申し込んでいただけると嬉しいです!
株式会社マネーフォワード 大阪 の求人一覧
株式会社マネーフォワード 京都 の求人一覧

関西開発拠点ホームページ


マネーフォワードでは、エンジニアを募集しています。
ご応募お待ちしています。

【会社情報】
Wantedly
株式会社マネーフォワード
福岡開発拠点
関西開発拠点(大阪/京都)

【SNS】
マネーフォワード公式note
Twitter – 【公式】マネーフォワード
Twitter – Money Forward Developers
connpass – マネーフォワード
YouTube – Money Forward Developers

Pocket