会計PlusのWebフロントエンドパフォーマンス改善

大阪開発拠点マネーフォワード クラウド会計Plus(以下、会計Plus)プロダクトのフロントエンドエンジニアをやってます、しばもとです。好きな食べ物は、ポンデリングです。

私が所属する会計PlusのWebフロントエンドで改善活動を行いました。その改善活動としてビルド時間の短縮、バンドルサイズの削減、Jestの実行時間短縮など同じフロントエンドエンジニアの方の役に立つと思ったので紹介させていただきます。

簡単な会計Plusの技術的な紹介

会計Plusのフロントエンドでは、次のツールを使用しています。

  • バンドルツールに、webpack
  • テストフレームワークに、Jest

これらのツールは、CI/CDのサービス CircleCI上で動かしています。また、フロントエンドライブラリとしてReact、型にTypeScriptを使用しています。

※ 説明の都合上、必要最小限の紹介をしています。

改善内容

実際に行った改善内容は、次の3つです。

  • webpack

    • 1.ビルド時間 高速化

    • 2.バンドルサイズ 削減

  • Jest
    • 3.(CircleCI上で) 実行時間 高速化

それぞれ、簡単に紹介します。

webpack ビルド時間 高速化

会計PlusのProduction向けwebpackビルド時間が、1分34秒かかっていました。ビルド時間が長いと、デプロイ実行時間が伸びてしまい、結果、リリース時間も伸びてしまうという課題があります。

CI/CDのプロセスを高速に回したいため、ビルド時間を1分以内に短縮したいと思いました。ビルド時間の目標値については、明確なゴールを持っていなかったため、きり良く1分としました。

改善前(Before)と改善後(After)のSpeed Measure Pluginログを載せます。

 // Before
 SMP  ⏱  
General output time took 1 min, 34.36 secs

 SMP  ⏱  Loaders
ts-loader took 1 min, 1.15 secs
  module count = 383
mini-css-extract-plugin, and 
css-loader, and 
postcss-loader, and 
sass-loader took 44.45 secs
  module count = 99
css-loader, and 
postcss-loader, and 
sass-loader took 43.95 secs
  module count = 99
modules with no loaders took 41.93 secs
  module count = 1433
url-loader took 0.16 secs
  module count = 17

// After
 SMP  ⏱  
General output time took 19.64 secs

 SMP  ⏱  Loaders
ts-loader took 6.66 secs
  module count = 383
mini-css-extract-plugin, and 
css-loader, and 
postcss-loader, and 
sass-loader took 8.42 secs
  module count = 99
css-loader, and 
postcss-loader, and 
sass-loader took 7.99 secs
  module count = 99
modules with no loaders took 6.1 secs
  module count = 1433
url-loader took 0.024 secs
  module count = 17

General output time took1 min, 34.36 secs から 19.64 secs に短縮されていることが分かります。

webpack バンドルサイズ 削減

会計PlusのWebpackのバンドルは、サードパーティ製のvendorと、アプリケーションコードのbundleの2つで分割しています。vendorのバンドルサイズが1.9MiBと巨大になっており、推奨サイズ (250 KiB) を大きく上回っていました。

CompressionWebpackPlugin を使い、gzで 505 KiB まで圧縮していますが、それでもなんとかバンドルサイズを減らせないかと思いました。

  • やったこと
    • tsconfig の compilerOptions.module を commonjs から esnext に変更
    • require構文からimport/export構文へ切り替えたことによる、TreeShaking効果で、デットコード削除
  • 結果
    • vendorファイルのバンドルサイズ 削減
    • 1.9 MiB → 649 KiB (約66%減)
    • bundleファイルのバンドルサイズ 削減
    • 600 KiB → 490 KiB (約19%減)
  • ⁠計測
    • Webpackの標準出力

改善前(Before)と改善後(After)の webpack build標準出力ログを載せます。

// before
Assets: 
  bundle-c3cf39f29f182f0cf63b.js (600 KiB)
  vendor-6b7bb5650011d7d589c2.js (1.9 MiB)
  vendor-6b7bb5650011d7d589c2.js.gz (586 KiB)

// after
Assets: 
  bundle-d21e45c581d2913ef503.js (490 KiB)
  vendor-211cffabccdad2e2c634.js (649 KiB)

特に、vendorのファイルサイズが大きく減少(1.9 MiB → 649 KiB)していることが、分かります。

CircleCI Jest 実行時間 高速化

ローカルマシン(MacBook Pro)でJestのテストを動かすと2分未満で完了するのに、CircleCI上では5分以上かかってしまっています。これは、ローカルマシンとCircleCIのマシンリソースの違いが原因と推測しています。 私が使用しているMacBook Proのマシンリソースは 8 CPU, 64 GB に対して、CircleCIは2 CPU, 4GB のマシンリソースです。

テストの早期フィードバックによって、フロントエンド開発をスピーディに行いたいため、CircleCI上のJestの実行時間を短縮したいと思いました。

CircleCIのテスト関連のワークフロー

Before

After

フロントエンドテスト(client_run_tests) が、改善前(Before)から改善後(After)で、5m22sから1m43sに削減できていることが、分かります。

改善を通して感じたこと

これらの改善は、特に目新しいことをしていないと思っています。遅いなと思う所で 計測→公式資料を読む→試す を繰り返しただけです。特別なツールを使ったわけでも、チューニングにコードをゴリゴリ書いた訳ではありません。シンプルに、公式資料の言うことを、そのまま試しただけです。

にもかかわらず、小さなコストで大きな改善ができました。これらの改善時間は、5営業日ぐらいです。

そこから学んだことは、特殊なことをせずに 公式資料をちゃんと読むという、当たり前なこと が、とても大切だと思いました。

以降では、当たり前な気づきを紹介します。

大前提として計測しよう

いきなり改善活動すると、どこまでやればゴールなのか迷ってしまいますし、オーバーエンジニアリングに陥ってしまうかもしれません。まずは、定量的に計測できるものを見つけて、計測してみましょう。

また可能であれば、可視化もしてみましょう。数値で表すよりも、全体の傾向などをつかめたりすると、何か新しい発見があるため、可能なら可視化もしてみましょう。

今回、使ったのは次のものですが、こだわりはありません。npm trendsで人気なものを選んだだけです。

当たり前改善1: 使われていないものは、捨てましょう

使われていないアプリケーションコードや、開発プロセス等で使われないスクリプトやモジュールたちは、一掃しましょう。

使われていないから、アプリを利用するユーザーにとって困らないと思うかもしれませんが、開発するエンジニアにとっては困ります。

使われていないものは、存在するだけで様々なコストがかかってしまいます。例えば、次の困りごとがあると思います。

  • コードリーディングするときに不要に読んでしまう
  • 不要な範囲まで影響調査してしまう
  • 使わないモジュールをアップデート対応してしまう

使われていないものは、ちゃんと捨てましょう。

当たり前改善2: ツールは最新にしよう

webpackやJestで実行時間を高速化したいと思ったとき、話題の爆速ツールを使ってみたくなる気持ちがあると思います(わかります)。その気持ちは、ぐっと抑えましょう。webpackやJestだって、素晴らしいツールです。

今回使っているフロントエンドツールはOSSであるため(ありがたい)、ツールを最新化することで、コントリビュータの方々からの改善を享受できます。その中には、パフォーマンス改善も含まれているやもしれません

webpackやJestなどのバージョンを、大胆に最新版にあげて試してみましょう。

当たり前改善3: 公式資料を読みましょう

改善するときに、どうやったら改善できるか手段を調べると思います。その際、個人で書かれているTipsを発見することがあります。それはそれでとても貴重ですが、最初に見るべきではありません。まずは、webpackやJestなどの公式資料を読んでみましょう。往々にして、そこにヒントがあるはずです。

実際に参考になったものを、共有します。

公式資料通り、標準に従ってシステムやアプリケーションを設計しておくと、先人の知恵を大いに享受できるため、できる限りはカスタマイズせずに、標準に合わせることは、あらゆる面でメリットがあります。

終わりに

改善活動は、一足飛びでやることではありません。一つ一つ順を追って改善していくことが大切です。ご参考になれば幸いです。

会計Plusでは、フロントエンドエンジニアを大募集しています! また、カジュアル面談もやっていますので、お気軽にどうぞ!


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

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

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

Pocket