AngularJSのリプレースにAngularを選んだ話

ビズリーチで「HRMOS(ハーモス)採用管理」のフロントエンドエンジニアをしています、浅井です。

HRMOS採用管理は、前身を含めると2014年に開発がスタートし、当初より Single Page Application (以下、SPA) を全面的に採用し、そのフロントエンドのすべてを AngularJS (以下、旧AngularJS) + TypeScript が担ってきました。サービスの拡大に伴って機能は増えていき、ソースコードは総計10万行まで膨れ上がってきました。

そこで現在は、旧AngularJSで記述されたコードを捨てつつ、新しいAngularを用いたコンポーネント指向のアーキテクチャに移行している真っ只中です。この移行で取り組んだ際の裏話を前編・後編のふたつに分け、前編では「AngularJSのリプレースにAngularを選んだ話」、後編では「Angularを用いたコンポーネント指向」と題してお届けしようと思います。

きっかけは旧AngularJSのパフォーマンスと将来性だった

2016年のサービス正式ローンチ後も機能の拡充と改善を精力的に行ってきましたが、最近機能を増やすたびに “遅いページ” が散見されるようになってきました。例えば、スペックの低いPCでInternet Explorerを用いてアクセスした場合、ページの遷移に5秒近く要するといった具合です。

この原因を調べていくと、旧AngularJS界隈では有名な、$watch 数の増大に起因するパフォーマンスの低下に辿り着きます。以下のアプローチを取ることにより、ページ遷移時間については5秒から3秒以内まで抑えるようにできました。 (長くなるため、詳細は割愛します)

  • AngularJSを最新版(1.4 → 1.5)にアップデートする
  • $watch の数を減らす、deep watchを使わないようにする
  • ディレクティブを遅延ロードさせる

しかし、パフォーマンス問題を根本的に解決できたとは言い難く、今後も旧AngularJSを用いて開発を続けることに対する不安が高まっておりました。

そんな中で、2016年10月に完全に刷新されたAngularが正式リリースされたことで、旧AngularJSの開発・サポートは終息する方向になることが想像できたため、Angularに移行が可能かどうか考えていくことにしました。

お菓子管理アプリを作ってAngularを試してみる

ちょうどこの頃、ビズリーチ社員である竹添(@takezoen)から「社内の技術共有会でなにかフロントエンドの話をしてほしい」という無茶ぶりが来たこともあり(笑)、部署内にあるお菓子コーナーの在庫を可視化する管理アプリケーション「ハーモニーお菓子管理」を作ってみることにしました。

※ 部署のメンバーからカンパを集め、好きなお菓子や飲み物を仕入れた、お菓子コーナーが運営されています。

ハーモニーお菓子管理は半分遊びで作ったものですが、

  • HRMOS採用管理を構成しているUIをAngularでも実現できるかどうか
  • パフォーマンスは向上しているのか
  • チームメンバーが習得して自走していけそうか

という点を検証する目的もありました。

Angularへのリプレースを決めた理由

なぜ旧AngularJS環境のリプレースにAngularを選んだのか。以下のポイントが決め手となりました。

  • これまでの積み重ねと経験値を活かせる

    • すでに旧AngularJS時代からTypeScriptで記述しており、メンバーがTypeScriptでの記述・実装に慣れていた
    • 旧AngularJS/Angular間で基となる設計思想は似ており、Service層のビジネスロジックはある程度転用可能であった
  • テンプレートHTMLに対してもコンパイル時にエラー検出ができる

    • 旧AngularJSはHTML内に誤ったマークアップを行なってもWebブラウザで実行するまでエラーとして検知できなかったが、Angularではコンパイル時にチェックされるようになった
      • デザイナーも安心してテンプレートHTMLのコーディングができるようになる
  • 公式コマンドラインツール「Angular CLI」の秀逸さ

    • プロジェクトの作成からビルド作業まで、一連の作業がコマンドラインで可能で、開発作業の効率化が見込める
    • ユニットテスト、e2eテストの実行環境も内包されており、複雑な設定なしですぐ使い始められる
  • Angularのロードマップが明確である

    • Angularチームによるメジャーリリースが半年ごと、またパッチリリースが毎週提供されることで、サービスの長期的な運用が確立できる
  • 周囲の好反応

    • 同僚のフロントエンドエンジニアにも触れてもらったとき、ポジティブなフィードバックをもらう
      • なんだかんだでこういう理由は大きい

あとは、包み隠さず言うと Angularが気に入っていて、Angularに愛があったから かもしれません(笑)

Angularを運用していく確信と覚悟が持てたので、最終的にはフロントエンド フレームワークを旧AngularJSから Angularに移行したい旨を上司に提案しました。 新しい技術を試してみる文化があり、またこれまでの機能拡充で積もってしまった技術的負債に対する課題感もあったことで、提案は比較的すんなり通りました。

Angular移行にあたって始めたこと

公式ドキュメントを翻訳して読み合わせた

Angular移行プロジェクトを立ち上げた後、Angularの公式ドキュメントを輪読形式で読み合わせることにしました。公式ドキュメントのチュートリアルを除くほぼ全ページを、事前に有志メンバーで公式ドキュメントの翻訳分担を行い、お互いの知見や認識を共有する会を1時間×週2回開催することで、メンバーのAngularの全体像と実装方法に対する理解が深まっていきました。

翻訳が終盤を迎えていた一部ページにおいて、気付けばAngularのマイナーバージョンアップによって公式ドキュメントの内容が大きく変わってしまっていた…なんていうハプニングもありましたが(笑)、公式ドキュメントからAngularの全体像を頭の中にインプットできたことで、なにか問題が出た際も「そういや公式ドキュメントのあのページに確か書いてあったな…」と索引付けができたことはとても大きかったです。

翻訳成果物を本家へ還元

チーム内だけで翻訳後のドキュメントを保管しておくのはもったいないので、翻訳したドキュメントの一部は angular-ja(Angularの公式サイトを日本語に翻訳するオープンソースプロジェクト)に還元しています。

翻訳成果物のPullRequest(一部)
翻訳成果物のPullRequest(一部)

後編に続く

後編では、実際にAngularでWebアプリケーションを再構築していく中で、中長期的な運用を行なうにあたって採用したアプローチを中心にお話したいと思います。