「ビズリーチ・キャンパス」は2016年にリリースされ、当時 Thymeleaf + Knockout.js の MPA として開発されていました。 現在、事業拡大に伴うユーザーの増加・機能開発に対応し、システムとしてのスケーラビリティを上げやすくするため、アーキテクチャの見直しや改善の真っ只中です。
この記事では改善活動で具体的に取り組んだことをご紹介します。フロントエンドの環境改善・統制の一例として、参考となれば幸いです。
ビズリーチ・キャンパスとは?
「ビズリーチ・キャンパス」のシステムは、企業・大学・OB/OG・学生・Adminのそれぞれのアプリケーションがあります。 就職活動をサポートするサービスなので、就活時期に合わせてピークが訪れ毎年新しい企画を実装・実行しながら進化を続けています。
当初の開発体制は?
事業に直結する新機能・施策の開発を主にしているスクラムチームの他に、ネイティブアプリのチーム、SREチームがありました。 私が2020年にスクラムチームに参画した当時は、開発時に再利用できないUIだったり、特定の画面のスタイルを修正したつもりが他の画面で崩れてしまったり、予期しない箇所で参照されている JavaScript など様々な問題が起き、結果ベロシティがなかなか安定しない状況になっていました。
フロントエンドで何が起こっていたか
大きく以下のような問題が起きていました。
- 構造化・コンポーネント化の問題
- CSS スコープが不明瞭な結果、開発コストが増大し、バグの原因に
- UI のコンポーネント化がされておらず重複コードが多発
- 同様の関数が記載されており、変更のたびに変更漏れや予期せぬエラーが起きやすい状態
- 静的解析、フォーマッタが無く、コードに統一感がなく可読性に欠けている
- アップデートが放置されていた問題
- 複数アプリケーションの依存ライブラリを一つの package.json で管理しており、ライブラリアップデートが困難
- レガシーな技術によって、ドキュメントも古く調べにくい
- テストコードが足りてない・検知できない問題
- E2E 以外のテストがなく、事前にバグに気づきにくい
- エラーを検知する機構がなく、問い合わせが来て初めて不具合を認知していた
課題をまとめつつフェーズを分けて改善する
そこで、以下の観点をもとに、既存の起きている問題をグルーピングしていきました。
- プロダクトへの直接的な影響をなるべく小さくする
- ユーザーが安心して使えるようにしていく(エラーが少ない状態でよりスムーズに使えるように)
- 開発体験をできる範囲で最大にする。(初回起動、ホットリロード速度、型情報など)
画像は実際に改善を提案するにあたって最初に作った資料です。長期でやっていくことやメリットの説明を丁寧に行いながら周囲を巻き込みフロントエンドの改善チームの組成に繋がりました。そして、段階を踏みながら改善活動を進めていきました。
第一段階:依存の最適化・開発速度を向上・バグを増やさない仕組みづくり
package.json の分割
まず初めにどこで何を持っているのか、不要なもの・ボトルネックになっているものは何かを判断するために、複数プロダクトをまとめている package.json をアプリケーションごとに分割し個別アップデート可能な状態を作り、 アプリケーションごとに必要なものを断捨離・最適化を行いました。
ミドルウェアの最適化とバージョンアップ
古い gulp, webpack で行っていたため初回起動、ホットリロードが30秒以上かかっていたところを、最新版に全てアップデートを行い、タスクランナーとバンドラを明確に分けることで開発中のホットリロードが10倍以上速くなりました。
静的解析を導入しコードのフォーマットを整える
「ビズリーチ・キャンパス」でのコーディング規約 + デファクトスタンダードなものを元に、社内公開で npm package を作成し、各モジュールに追加。 GitHub Actions 上でエラー検知できるように CI 環境を整備、古くなっていたドキュメントを廃止。 Lint エラーは粛々と修正しました。
これらの活動により、コードのフォーマットが整理され可読性が高まり、手を入れるべきコードベースをより判断しやすくなりました。
第二段階:監視体制の構築、脆弱性対策
Sentry を追加し、エラーを検知し対応可能な状態にしました。 加えて、 yamory や Snyk を活用しながら対応すべき脆弱性対応を行いました。
アプリケーション内のエラーハンドリングの見直し、 コツコツとエラー解消を行うことにより、2年間で94%のエラー削減に成功しました。
1日あたり各環境で何十件も通知されていたものが、週に1,2件のペースに減りトリアージし切れるようになりました。
第三段階:レガシーフロントエンドの解消
- React + TypeScript の導入と jQuery, Knockout.js を減らす活動・リプレイスも行う
古い構成の画面を重たい機能から新しいライブラリ・構成にリプレイスしつつ、ドキュメント作成などを行い学習しやすい環境を構築しました。
- デザイナーと連携し、アプリケーション内の共通コンポーネントを作り込む 同時にフロントエンドをレイヤリングし責務を明確にしていきながら、ロジックと UI を分離しデザイナーでも UI 修正を可能な状態にしました。 Storybook を活用し共通コンポーネントにはユニットテストも追加しています。
結果として、アプリケーションの一部を React 化、新規ファイルは全て TypeScript 化され順調にプロダクトは改善される状況になりました。 グラフ上からも、古いファイルが削除され TypeScript、React Component に置き換えが進んでいることが読み取れます。
新しいフロントエンド環境を広げる活動
React を採用してから、開発メンバーがスムーズに開発できるようにドキュメントの構築に加え、 FAQ を設けました。 ドキュメントでは補足できなかった部分やメンバーからのフィードバックを集約し、足りないものや新たな疑問が生まれる場合はペアプロや新規ドキュメントにて補足するような形で開発チーム全体を常にサポートしています。
開発チーム全体からいつでもカジュアルに質問・疑問を集めて、一次回答の必要に応じて新規ドキュメントの作成・コードの修正・改善をしています。 またReactの経験者も少ない状態でしたので、勉強会を行い知見を広げる活動を日々行っています。
最後に
機能追加が多い画面、新規画面はリプレイスがほぼ完了し、アプリケーション全体ではエラー監視できる状態、共通コンポーネントやサービスのコアとなる機能にテストも追加できました。
加えて、型情報が追加され React の世界ではコンポーネント化され UI とロジックの分離ができました。
2年間の改善を置き換え率で見るとまだ道のりは長いですが、継続的に取り組んでいます。
今後は共通 UI コンポーネントをブラッシュアップし他アプリケーションへの展開、コンポーネント駆動開発の実現、開発チーム全体のフロントエンド力の強化などを考えて活動中です。
以上、フロントエンドの環境改善・統制の一例として、参考となれば幸いです。