みなさん、ライブラリのアップデートできていますか?
気を抜いているとあっという間にメジャーバージョンがアップデートされ、破壊的な変更や依存ライブラリの非推奨化などで気づいた頃にはバージョンアップに多大な工数がかかるなんてことになりがちです。
可能であれば CI 等で定期的にアップデートをチェックしこまめにリリースできる環境が良いと思います。しかしさまざまな理由から必ずしもそのようになっていない場合が多いのではないかと思います。
個人でやっている分には勝手にどうぞで終わる話ですが、プロダクションのコードに対して実行する場合その行動は慎重にならざるを得ません。
そういった環境下でライブラリの大幅なアップデートを行う際に気をつけていることを書いてみようと思います。
※ 著者は Web フロントエンドエンジニアであるため、この記事ではフロントエンドのライブラリのアップデートをする前提で話を進めます。
ライブラリのアップデートを迫られる状況のパターン
スピード重視の新規機能開発により保守体制が整っていない
プロダクトのフェーズによってはスピード重視で新規機能開発を行うケースも多くそういった環境ではしばしば保守が蔑ろにされがちです。出だしは順調でもしばらく開発を進めていると必ず問題にぶち当たります。
問題は複雑になりすぎたコードにあるかもしれませんが、コードだけではなくそれを取り巻く周囲にも問題があります。使用しているホスティングサービスが Node.js 対象バージョンを引き上げた、使用しているライブラリのセキュリティに問題があるなど。
突然知らないプロダクトの保守を任される
何年も前に先人が作ったサイトの更新をお願いされることもあるでしょう。
あまりにも古く機能がそこまでなければ新しく作る方がはるかに工数が少ないかもしれません。しかしそれが実は現在も運用されているコーポレートサイト・EC サイトだったりすると絶望感が増します(ドウシテこんな状況に・・・)。
状況から判断する
さまざまな状況があるなかで、古いものは新しくすべきと決めつけてアップデートを実行すべきではありません。
期日や人員、歴史的な経緯など・・・考慮すべき点はいくつかあります。それらを加味してアップデートすべきか、今回は諦めるか、別の手段を取るか、を考えます。
無理にアップデートを行うと、バグが出てその対応に追われることになります・・・
冷静に考えればなんとかなりそうなものも、対象が本番環境だったりすると精神的なダメージでパフォーマンスが落ちて辛いんですよね、自分だけではなくメンバー含めチームへの精神ダメージを軽減するためにも慎重に考えて行動すべきです。
そもそも・・・
本来はこんな状況にならないように保守環境が整っていることが理想です。
何事も途中から予定になかった行動をするよりも最初からその想定で動いていた方が圧倒的に楽です。
色んな事情があると思いますが、未来の担当者(他人または自分かもしれません)のために保守環境を整える時間を得ることを交渉した方がいいでしょう。
継続的なアップデートにおいては、静的解析・自動テストなどの導入などでレビューや手動テストなどリリースにおける工数を下げることができる仕組みを取り入れるのが良いです。
例えば自動テストが充実していれば機能に対する手動テストを回避することでリリーススピードを上げ、そもそものライブラリのアップデートが抱える煩雑さを抑えることができるかもしれません。
どんな環境を整えるべきかはプロジェクトによるので、それについてはまた別途議論すべきです(プロジェクトの性質・チームの規模・スキルなど)。
ライブラリのアップデートの提案から実行までの大まかな流れ
極端な状況であればあるほど解決しなければならない問題は多いのですが、重要なのは優先順位の決定だと思います。限られた工数の中で行うことがほとんどだと思いますので効果が最大になるように選択すべきです。
1. とりあえず一通り問題を洗い出す
なぜライブラリをアップデートする必要があるのか、アップデートを行うことでどんな恩恵が得られるのか、論理的に洗い出します。ただ「新しいバージョンが出たから」では弱いです。簡単にリリースできる環境が整っていれば話は別ですが、工数がかかるとなると他のタスクとの優先順位をつけるために指標が必要になります。
2. 期限はいつまでか?人員はどれほどか?
無限のリソースがあるわけではありません、期限や人員により対応できる内容が変化します。
3. おおよその工数を見積もり取捨選択を行う
1 で出た問題を解決するための工数をリソースを加味して見積もります。ここで正確に見積もることはできないと思うのでおおよそで良いです。見積もりができたら他のタスクとの兼ね合いも含めてチームに相談したりなどして取捨選択をしましょう。
4. なるべく細かいタスクに分割する
取り組む問題がハッキリしたら詳細を詰めていきます。詳細を詰める過程で工数に変化があるようであれば改めて本当に対応すべきか考え直します。
また タスクに落とす時はなるべく細かくした方が良い と考えています。こういった見た目や機能の追加や変更を伴わない作業は時間のかかる割に進捗が外部からわかりにくいからです。作業者ではなく外部(上司・レビュワー・他部署の方などなど)に進捗を伝えるためにもタスクは細かく切った方が良いと言えるでしょう。作業者に対してもいくつもあったタスクを小気味よく DONE にしていけるとゲーム的な面白さを感じてやる気につながる効果もあるかもしれません。
5. 実行
決まったらあとは作業あるのみです。
ですが実際に作業をしてから発覚する問題もあります。その場合は 1 人で長時間かけてなんとかしようとせずにチームに相談すべきで、その上でさらにタスクを見直すべきです。
ライブラリのアップデートによる工数の見積もり時に確認すること
ライブラリをアップデートするといってもその内容は簡単ではありません。
マイナーバージョンのアップデートだけならまだしもメジャーバージョンとなると破壊的変更によりコードを修正する必要があるかもしれませんし、依存の状況によっては別のライブラリをアップデートする必要が出てくるかもしれません。
アップデートにおける影響範囲はやってみないとわからないこともある一方である程度は事前に調べることができます。
プロジェクトの概要を把握する
まずは何より大前提として対象のプロジェクトについて把握している必要があります。
常に触り続けていたプロジェクトなら問題ないかもしれませんが、そうで無ければどんな Web UI フレームワークを使用しているのか?からインフラ構成までざっくりと把握しておきましょう。
ライブラリのアップデートに限るとここで重要なのは Node.js のバージョンを把握することです。場合によっては特定の Node.js のバージョンじゃないとインストールできないライブラリがあったり、はたまた Node.js が古すぎてサーバーにデプロイできないので Node.js をアップデートする必要があるというパターンまであり得ます。
プロジェクトにドキュメントが残されていればそれで把握できるかもしれませんが、もし無ければ package.json やどんな設定ファイルが置いてあるか、CI/CD の設定がどうなっているか(DNS を確認しないといけないパターンもあるかもしれません)である程度把握できると思います。
依存関係も含めたアップデート対象のライブラリを洗い出す
小さなライブラリならそれほど気にする必要はないかもしれませんが、Web UI フレームワーク等の大きなライブラリをアップデートする時はその依存ライブラリも一緒にアップデートしなければならない可能性が高いです。
例えば Next.js であれば React や TypeScript などがその対象にあたります。
大きなライブラリであればアップデート用のツールが提供されておりそれを実行するだけで解決したりしますが、プロジェクトの規模が大きいと実は別の状態管理ライブラリにも React への依存があって・・・となりがちなので一通りリストアップしておいた方が無難です。
依存については公式ドキュメントに書かれていることもありますが、手っ取り早いのはライブラリの package.json をみに行くことです。
例えば Next.js の場合 React は v19.0.0, TypeScript は v5.7.2 で書かれていることがわかります。
あくまでこれは Next.js というライブラリがこれらのバージョンを使って書かれているだけで、Next.js を使うプロジェクトも完全にこれに合わせなければならないというわけではありません。
ですが、これ以上のバージョンだったりあまり古すぎたりするとエラーの原因だったりそもそもライブラリがインストールできなくなったりするので指標としてリストアップしておくと参考になります。
これらの情報とプロジェクトにインストールされているライブラリの情報とを照らし合わせて差分を取得します。
ライブラリのアップデートによるプロジェクトへの影響を調べる
ある程度アップデートすべきライブラリの洗い出しが終わったら次はそのライブラリをアップデートすることで発生する影響を調べます。
前の章でも書きましたが、大きなライブラリであればアップデート用のコマンドが用意されており、修正内容についても自動でやってくれたりします。
ですがここでも同じように規模がデカくなるとコマンドで自動的修正するには限度があったりそもそもそういったツールが用意されていない場合があります。
ツールが用意されていなくてもドキュメントを用意してくれているパターンがあります。
「ライブラリ名 migration」などで検索するとヒットすることが多いのでそれを確認しましょう。
Next.js の場合 Upgrade Guide というページにたどり着くことができます。
https://nextjs.org/docs/app/building-your-application/upgrading
しかしドキュメントがないライブラリの方がほとんどです。
その場合はリポジトリのリリースノートを確認しに行きます。
お馴染み Next.js の場合は以下から確認できます。
https://github.com/vercel/next.js/releases
現在の次のバージョンからアップデートするバージョンまでのリリースノートに目を通すことで変更内容を知ることができます。
ドキュメントやリリースノートに挙げられている変更点とプロジェクトのコードを見比べて対応すべき内容をリストアップします。
おわりに
思えば私にとって開発時に辛いなと思うことはライブラリのアップデートと共に訪れていた気がします。アップデートをリリースしたら予期せぬところが壊れていたとか、この依存関係のせいでアップデートできないので今からフルスクラッチで書きます(納期は変わりません!)とか、、そういう辛い現象はメンテナンスしやすい環境を作ることで和らげることができると身に沁みて感じている一方で、力の及ばぬところから突然降りかかってくることもあるわけで、せめて実行する前に不明な要素はなるべく排除して挑めればと思う次第です。