こんにちは、みんなのマーケットでフロントエンドエンジニアをしている山本です。
先日、AngularJSで書かれていた一部のページをReactでリプレースするプロジェクトのリリースが無事終わったため、経緯や知見を共有いたします。
前提の共有
リプレースの背景を説明する前に、必要な前提の共有をいたします。
弊社が提供するサービス、くらしのマーケットのWebアプリケーションには大きく分けると2つのページが存在します。
1つ目が、一般ユーザーが利用する「ユーザー側」と呼ばれるページです。「くらしのマーケット」と検索して出てくるページがこちらです。
2つ目が、くらしのマーケットに出店している店舗向けの「店舗管理システム」と呼ばれるページです。
今回リプレースを行ったのは、2つ目の店舗管理システムの「カレンダー」を表示するページです。
この店舗管理システムのカレンダー周りの改善施策を行う予定があったのですが、まず先にAngularJSからのリプレースを行ったほうが良いのでは?という話になりました。
フレームワークの選定について
AngularJS
からのリプレースというと、メジャーバージョンアップのAngular
ではないのか?と思う人も多いかもしれません。
しかし AngularJS
と Angular
では、名前こそ踏襲されているものの文法や設計がまるで異なります。
特にコンポーネントの定義方法やデータバインディングの文法が違うため、実質的にフルリプレースになることは避けられないと考えられました。
そのため、リプレースすると決まった段階で「どうせ大きく変わるのであればその他のフレームワーク(ここでは便宜上VueやReactもフレームワークという括りにします)との比較をしても良いのでは」という提案がありました。
タイトルでも分かる通り、最終的に React
に移行することに決定しましたが、なぜReactを選定したのかという理由を以下で説明いたします。
「前提の共有」で話した通り、今回リプレース対象となったのは店舗側システムのカレンダー画面であり、カレンダーの実装がもっとも重要なポイントでした。
そこで以下の理由から、リプレース対象となるフレームワークはfullcalendar
というライブラリが対応しているフレームワークにすることになりました。
- 現行の実装では
fullcalendar
というライブラリが用いられている fullcalendar
はカレンダーの表示や予定の登録・移動などの実装を非常に簡単に行うことができるライブラリであり、その他のライブラリではリプレースに長い時間がかかってしまうことが懸念される- 直近の開発で新しいバージョンの
fullcalendar
を用いた実績があり、ノウハウも一定数存在した
公式ホームページのGetting Started見ると分かる通り、 fullcalendar
は React/Vue/Angular
の3種類のフレームワークに対応しています1。
さて、この3種類のフレームワークは2021年時点でもっとも有名なフロントエンドフレームワークだと思います。
それぞれのメリット・デメリットを比較した結果、以下のようになりました。
ただし、弊社・チーム特有の事情も含まれているためすべての状況で以下の通りになるとは限らないという点に注意してください。
メリット | デメリット | |
---|---|---|
Angular | すでにユーザー側のページで広く使われている 周辺ライブラリの選定が不要 TypeScriptとの相性が良い |
学習コストが比較的高い State of JSでネガティブな意見が多い |
Vue | 入門ハードルが低い SFCを使うことでデザイナーとの協力もしやすい |
TypeScriptとの相性が発展途上 チーム内に経験者がいない |
React | TypeScriptとの相性が良い 利用者数・満足度共に高い |
ライブラリ選定が必要 JSX記法に対する慣れが必要 |
次にこの表の中身についてより詳しく解説いたします。
Angular
Angularの一般的なメリットとして、フルスタックフレームワークとして設計されており周辺ライブラリの選定に時間が取られず開発に集中できるというものがあります。
Reactでは状態管理や通信、フォームの実装などさまざまな場面でサードパーティ製のライブラリが必要となっており、それぞれのデファクトが数種類あるということも珍しくありません(Vueの事情についてはここで書けるほど詳しくないため言及しないことにします)。
他にも、TypeScriptで設計・開発が行われておりTypeScriptとの相性も良いことが知られています。
また、これは弊社特有の事情ですが、くらしのマーケットのユーザー側のページはAngularで作られているページが多く、ある程度触れるエンジニアがいることもメリットの一つとして挙げられます。
一方でデメリットとして、学習コストの高さが挙げられます。
先ほど「ある程度触れるエンジニアがいることもメリットの一つ」と言いましたが、残念ながら現時点では、Angularを知らないエンジニアに対する教育環境が整っているわけではありません。
そのため開発時には基本的な機能のみを使うことが多いのですが、「もっと良い書き方があるのではないか」「これはAngular的に正しいのだろうか」と思いながらコードを書くことも多いです。
また、JavaScriptに興味を持つ世界中のエンジニアへアンケートを取った結果をまとめている State of JS
というサイトで、Angularに対する否定的な意見を持つ人が増えたり人気が下落傾向であることも懸念点の一つでした。
Vue
Vueのメリットとして、入門ハードルが低いというものが挙げられます。
AngularではTypeScriptやAngularのモジュールシステムが、ReactではHTMLとJSXの違いがほぼ必須知識と言えるでしょう。しかしVueでは、HTML/CSS/JavaScriptを知っていればコードを書き始めることができます。
一方でデメリットとして、テンプレート内の式に対する型チェックが効かないなど、TypeScriptとの相性がAngularやReactほど良くないという点が挙げられます。
調べた限りだと Vetur
というツールで解決できそうですが、こちらを見ると「頑張って対応している」という印象が強く、TypeScript単体で型チェックが行えるReactと比べるとレイヤーが1つ増える分バグが発生する可能性も高まってしまいます。
今後機能開発やバグ修正を行う際に、型によって守られた開発ができないというのは大きなデメリットだと考えられます。
また、Vueは学習コストが低いという話もよく聞きますが、個人的には懐疑的です。
Vueのディレクティブの一覧を見てみると、16種類の異なる機能を持ったディレクティブが掲載されています。
ディレクティブ以外も含めるとさらに多くの機能を覚える必要があります。
これを踏まえると、「入門しやすい」「学習曲線が緩やか」というのはおそらく真実だと思いますが、「学習コストが低い」は嘘だと思っています。
最も大きな懸念点となったのが、チーム内にVueを(少なくともAngularと同程度以上に)使える人間がいなかった点です。
Angularであればチーム内の全員が最低限は扱うことができますし、Reactであれば私がメンバーに教えることができるものの、Vueを扱えるメンバーがいない状況だとリプレースにどれくらい時間がかかるか見積もることが難しく、これが最大の懸念でした。
React
最後にReactのメリット・デメリットについてです。
Angularの際にも挙げたState of JSによると、2020年のランキングは2位(1位は選定外の svelte
でした)、満足度も非常に高いという非常に人気を博しているフレームワークです。
もちろん人気のみでフレームワーク選定をするわけにはいかないので、「なぜ人気があるのか」「具体的にどのようなメリットがあるのか」を検討する必要があります。
Reactを選定した際に得られる大きなメリットとして、TypeScriptの恩恵を最大限に得られるというものがあります。
JSXというJavaScript内にHTMLのような構文を書ける記法をTypeScript自体がサポートしているため、Vueの際に課題となっていたテンプレート内での型チェックも問題なく行うことができます。
Reactの周辺ライブラリも型安全性を意識したライブラリが多いため、周辺ライブラリまで含めて恩恵を受けられると言えるでしょう。
一方でデメリットとして、スタイル方法が統一されていないというものがあります。
VueやAngularにはデフォルトでコンポーネントとスタイルシートを紐付ける仕組みがありますが、対してReactには、コンポーネントにスタイルを適用する方法が複数存在します。
選択肢が多く状況に適した方法を取れるという見方もできますが、周辺ライブラリの選定コストがさらにかかるという問題にも繋がります。
しかし今回、既存のアプリケーションをリプレースするという都合上このデメリットは軽減可能でした。
というのも、すでにCSSファイル2が存在するためこれを流用するという方法が第一選択肢となったためです。
JSX記法に対してネガティブな印象を持つ方もいますが、個人的にはこれは慣れの問題が大きいと感じています。
実際、今ではReactが大好きな筆者も、実際に使い始める前まではJSX記法に対して非常に気持ち悪いという印象を持っていたためです。
上記の表ではデメリットの欄に入れましたが、現実的なデメリットではないと考えられます。
結論
今回私達は、以下の理由で React
を使うことを選びました。
- TypeScriptとの相性の良さに起因する開発体験の良さや開発効率の高さが優秀かつ重要だと考えられたこと
- Angularの学習コストの大きさや人気の低下がリスクだと考えられたこと
- Reactのデメリットとして考えられる項目は回避、対応可能であると判断できたこと
リプレースの流れ
Reactでリプレースすることが決まったあとは以下の流れでリプレースを進めていきました。
- 以下の流れでチームのメンバーにReactの勉強をしてもらう
- https://zenn.dev/likr/articles/6be53ca64f29aa035f07
TODOアプリ
の作成- およそ一週間です
- 上記と平行して、既存のビルドシステムにReactを組み込んで開発が進められるように環境の構築
- リプレース対象の画面に含まれる機能の洗い出しとストーリーポイントの算出
- ゴリゴリ実装&QAフェーズ
- 実装とQAを含めておよそ一ヶ月の期間が必要でした
- リリース🎉
リプレースを進める中で気をつけたこと
チーム内の他のメンバーがReact未経験であったため、リプレースを進める際には以下の点に気をつけていました。
1. チームメンバーから質問があった際には可能な限りすぐに回答する
チームメンバーにはReactの公式サイトや役に立つチュートリアルページを用いて事前にある程度勉強してもらっていましたが、実際に開発を進めてもらっているとチュートリアルでは不十分だった点が出てきます。
Reactに関する知識が少ない場合、玉石混交なインターネット上の記事を自分で調べてもらうより私に聞いてもらった方が早く解決する可能性が高いと考え、一旦私に聞いてもらうようにしていました。
2. デイリーミーティング後にエンジニア質問タイムを設ける
チームで行うデイリーミーティングでは、その日やることや困っていることについてエンジニアやPMを交えて話しているのですが、デイリーミーティングが終わったあとにエンジニアのみで集まりReactやその周辺ライブラリについてよくわからなかった部分について質問する会を行っていました。
3. メンバーからの提案に真摯に向き合う
これは言ってしまえば当たり前とも思えることなのですが、個人的に大切にしていたことなので書いておきます。
チームメンバーから「このような書き方もあると思いますがどうでしょうか?」というような提案があった際に、「初心者からの提案だ」という意識で適当に聞いてしまうことが無いように努めました。
慣れないライブラリを使って試行錯誤しつつ実装していく中で一生懸命考えた提案を適当に聞き流されてしまうと、モチベーションに大きな悪影響を与えると考えたためです。
大変だった点
リプレースを進めるに当たり、大変だった点がいくつかあったためそちらも共有します。
1. タイムゾーンの扱い
今回リプレースする対象がカレンダー画面ということもあり、タイムゾーンの扱いに少し苦労する点がありました。
くらしのマーケットは日本国内でのみ提供しているため、デバイスのタイムゾーン設定によらず日本時間で予定を表示するという仕様でのリプレースとなりました。
fullcalendar
自体にタイムゾーンを固定して表示する機能があるものの、別途プラグインを追加する必要があった上にプロジェクトで使用している時刻操作ライブラリである date-fns
に対応したプラグインがありませんでした。
しかし、fullcalendar公式が提供している moment.js
向けのプラグインのソースコードを読んでみたところ20行以下で実装されていたため、これと同じような処理を date-fns-tz
というライブラリで再実装することで無事にタイムゾーン問題を解決することができました。
2. 既存のCSSを流用できなかった
もともとAngularJS版のfullcalendarを使っていたため、CSSファイルは同じものを流用できるのではないかと考えていました。
しかし実際には、fullcalendarのバージョンアップにともなうCSSクラス名やDOM構造の変更によって、同じCSSファイルを流用することはできませんでした。
これに関しては地道に移植をして動作確認時に問題ないかを見ていくことで対応しました。
概ね同じスタイルであれば厳密に同じで無くても良かったのが幸いでした。
今後について
先日リプレースとリリースが完了しましたが、もともとリプレースを行う理由であった店舗管理システムのカレンダー機能への改善施策はこれからです。
Reactに置き換えたことで本当に良かったのか、これから判断していければと思っています。
みんなのマーケットでは、くらしのマーケットの開発を手伝ってくれるエンジニアを募集しています!
詳細はこちらをご覧ください!