本記事は エムスリー Advent Calendar 2020 の 7 日目の記事です。
エムスリーエンジニアリンググループの山本です。 所属している電子カルテチームのフロントエンドは技術的な負債を抱えています。 使用しているライブラリのバージョンが古かったり、数年前にアーカイブされていたりします。 なによりフロントの資産の半分が AngularJS 依存となっています。
そんなフロント環境ですが TypeScript の導入 + React のバージョンアップなど負債の返却に向けて前進しています。
TypeScript の導入
現在 JavaScript100%のフロントですが、新規開発にTypeScript を使いたく導入しました。 本来は Babel のバージョンを 7 にして TypeScript をトランスパイルしたかったのですが、 AngularJS 向けプラグインに起因する問題で影響範囲や工数が少なくありませんでした。 そのため今回は ts-loader 使う事で素早く、既存の影響を出さずに TypeScript を導入しました。 Babel のバージョンが上がるまでの期間限定です。
React のバージョンアップ
直近でメジャーバージョンに2つ遅れをとっていたのですが、先日 バージョン 16.13.1 にアップデートし念願のhookが使えるようになりました。
React とそれに依存しているライブラリのバージョンをあげ、CHANGELOG や Release note を確認しつつ修正をしていくという一般的なやり方で対応しましたが、 無事にバージョンアップとはいかずにモーダル関係の不具合がでました。
モーダルが閉じない
Modal を使っている部分で一箇所だけ下記のような実装がありました。
<Button onClick={() => setState({show: true})}> ダウンロード <Modal show={show} onHide={() => setState({show: false})}/> </Button>
ボタンを押すとモーダルが表示される実装ですが、 Modal ライブラリの変更 (React.Portal を使うようになった) の影響でモーダルを閉じる際にも、Button のイベントが発生するようになりました。 モーダルを閉じるイベントの後にモーダルを表示するイベントが発生した結果モーダルが閉じなくなっていました。
ただよく考えてみると、Button の子要素に Modal があるほうがおかしいので、React.Fragmentを使い親子関係をなくす対応をしました。
モーダルが表示されない
AngularJS と React でそれぞれモーダルを表示するライブラリを導入しているため、zIndex が衝突する事象が発生していました。 それを回避するために React 側のモーダル の date-reactroot 属性に対してスタイルを当てていたのが原因でした。 CSS が React の内部実装に依存しているとは思っていなかったです。 こちらに関しては根本的な原因を対処するのに時間がかかるため依然としてライブラリの内部実装に依存するスタイルをあてています。
既存の実装次第なところもありますが素直にバージョンアップとはいかないものだなと感じました。 以下はバージョンアップをしていくなかで感じたことです。
技術的負債となってしまったライブラリから学んだ事
- 公開されていない API は使わない
あたりまえのようですが、特定の要件を満たすために hack 的なことをしてしまうこともあるのではないでしょうか。 その場合は場当たり的な解決になり、バージョンアップで壊れるなど将来の負債になる可能性は高いです。
- スター数が少ないライブラリを避ける
スター数がライブラリの評価というわけではありませんが、スター数が少ないライブラリはメンテナンスがされなかったり、バージョンアップ時の CHANGELOG 等が充実していない傾向にありました。 マイナーなライブラリやプラグインは運用の観点から辛くなる可能性が高いので導入時はしっかり検討したほうが良さそうです。
- forkは慎重に
React のバージョンアップに 独自に fork されたライブラリの修正が必要でした。 機能追加のために独自 fork をするということは、OSS のメンテナンスから外れるため保守の対象が増えてしまいます。 fork するのではなく PR を出して OSS に貢献できるのが理想ですね。
- 変更に強くする
interface に依存させる作りにしたり、メソッドでラップしてあげるだけでライブラリの変更が楽になります。 また必要以上に依存させないことも大事だと思います。プロジェクトに RxJS を導入しているのですが 、React の DatePicker のようなコンポーネントにも使われていたりします。DatePicker の機能を実現するのに Rx.js は不要なので、これは RxJS の依存とその保守の対象を増やすことになります。依存は少ないほうがいいので、ライブラリは必要な時に必要なだけ使うのが望ましいのではないでしょうか。
感想
ライブラリを導入する際はそのライブラリが将来技術的負債になる可能性があること、 誰かがそのライブラリを保守しなければならないことに自覚を持つ必要があるのだなと学びました。
ライブラリのメンテナンスのようのな作業は後回しにしがちだと思いますが、後回しにすればするほど難易度と工数が上がる場合が多いと思います。 今後は定期的にバージョンアップをできる仕組みを導入したいです。
We are Hiring!!!
電子カルテチームでは現在 UI/UX 改善というプロジェクトがスタートしています。 6 年前のフロントを未来へと変えていくと同時に技術的な負債を一気に返却する機会でもあります。 React + TypeScript でNo.1 クラウド電子カルテをより良くできる大チャンスです。
12/14(月) 19:00~ 「エムスリーデジカル」チームの採用説明会を行いますので、興味がある方はぜひ!!
カジュアル面談もやってます