🧹
ReactのSPAで外部ライブラリを整理するためにやったこと
この記事は過去に書かれたもので、一部の情報が現在の状況とは異なっている部分もあります🙏でも、根っこの考え方や大事にしていることは、今もそんなに変わっていません!
はじめに
同プロジェクトでは設計段階からのリファクタリングを並行して進めており、この記事では外部ライブラリを整理した話についてご紹介します。
課題
まずはリファクタリング前の課題です。
使用している外部ライブラリは開発が開始された2020年12月頃にインストールされたバージョンのままで、Reactもv16.13.1でありhookは入っているもののメジャーバージョンが2つ遅れている状況でした。
その結果
- 外部ライブラリの新機能が使えない
- 新しいライブラリが使えない
- ライブラリのバグがそのままになっている
- 情報が古いため技術的な調査に時間がかかる
- 脆弱性が発覚した際の対応に時間がかかる
などの課題があり、開発速度の低下につながっていました。
またGreenfile.workの各アプリケーションでは共通の内製Componentライブラリを使用しており、その内製ライブラリもバージョンがメンテされていなかったため、各アプリケーションの外部ライブラリのバージョンが上げづらくなっていました。
どのように外部ライブラリを整理していったか
大きく以下の4ステップで進めました。
- React16からReact18へのアップデート
- webpack4からviteへの移行
- ReduxをswrとuseContextに移行
- その他のライブラリのバージョンアップ
React16からReact18へのアップデート
まずはReactのバージョンアップです。
Reactのバージョンが古いと既存ライブラリのバージョンアップや新しいライブラリの導入など、全てに制約がかかるため最初に対応しました。
対応方針
具体的な対応方針としては
- 今回はGreenfile.workの他のアプリケーションのバージョンアップはやらない
- 定期メンテナンスの指針や方法などは決めない
- 関連ライブラリはReactのバージョンを上げるために必要な最小限の範囲でのみバージョンを上げる
と決め「Greenfile.work入退場のReactのバージョンを最新にする」をゴールとして、最小限のスコープで進めることにしました。
これはReactのバージョンがGreenfile.workの他のリファクタリングのボトルネックになっていたため、最速で対応するためです。
具体的な対応作業
内製ライブラリとGreenfile.work入退場のそれぞれで破壊的変更の対応を行いました。
内製ライブラリはreact18対応済と未対応でブランチを分け、他のGreenfile.workのアプリケーションに影響がでないように運用することにしました。
- React17の破壊的変更の対応
- イベント委譲の変更
- [開く]ボタンをクリック
- root elementに登録されたhandleOpenが発火してになり、にが登録される
- root elementはdocumentの内部にあるためバブリングしdocumentに登録されたhandleOutSideClickが発火して、になる
v17の破壊的変更の中で対応が必要だったのはイベント以上の変更のみでした。
React公式の図がわかりやすいですが、v16まではに登録されていたイベントハンドラがroot elementに登録されるようになりました。

この変更によってモーダルのような外側をクリックしたら閉じるComponentの挙動が変わったため対応しました。
具体的には
のようにが外部かどうかを判定して閉じるハンドリングをすると、v17では
となり、開いた瞬間閉じてしまいます。
そのため以下の記事を参考に、内部のモーダルの最も外側の要素でイベントのバブリングを止めるような実装に変更しました。
また一部上記の方法だと対応しきれないComponentは、documentをroot elementに置き換えて対応しました。
- React18の破壊的変更の対応
- renderからcreateRootに変更
- React.FCの暗黙的なchildrenの削除とReact.VFCのdeprecate
- StrictModeの挙動の変化
- その他に対応が必要だったライブラリ
- @testing-library/react-hooks
- connected-react-router
- @testing-library/react
- react-select
- typescript
- @typescript-eslint/eslint-plugin
- @typescript-eslint/parse
v18はReact自体のアップデートはスムーズでしたが関連ライブラリの対応が多かったです。
Greenfile.work入退場はリファクタリング中にTypeScriptへ移行した際にReact.VFCを使ってComponentを定義し、明示的にchildrenの型を指定していたため→から置換するのみでした。
内製ライブラリはComponentの型定義の方法が揃っていなかったため、必要に応じてchildrenの型を指定して対応しました。
@testing-library/reactの13系からhookに関するAPIも統合されてため削除しました。
react-router-domのバージョンに合わせてバージョンを上げました。
reactのバージョンに合わせてバージョンを上げました。
reactのバージョンに合わせてバージョンを上げました。
react-router-domのバージョンに合わせてバージョンを上げました。
webpack4からviteへの移行
次はビルドツールの対応です。
viteへの移行の背景
選択肢として上げたのは以下です。
- webpack v5に上げる
- Next.jsへの移行
- viteへの移行
結果としてviteへの移行を選択したのは技術的な側面よりも弊社の状況に合わせた消去法的な理由です。
まず全員がフロントエンドやバックエンド間やアプリケーション間を跨ぎながら開発をする環境で、webpackを運用していくのは難しいと考え、webpackからの乗り換えを決めました。
また現状、「内製ライブラリのComponentがReact Routerに依存しておりルーティング手法の変更がすぐにはできない」かつ「CSRのみで要件が満たせる」という理由で、Next.jsではなくviteへ移行を決めました。