Hipcamp が Claude Code で Expo SDK をアップグレードした方法
四半期単位からスプリント単位へ——Hipcamp は Claude Code を使って 40 以上の React Native 依存関係を更新し、新アーキテクチャへ移行して Expo 54 でリリースした。
日本語
コピー

この記事は Armaiz Adenwala が執筆した——Armaiz は Hipcamp でモバイルアプリの体験を担当している。
…
React Native のアップグレードは昔からエンジニアを悩ませる種だ。不慣れなネイティブコードに触れ、重要な依存ライブラリに向き合い、破壊的変更に対処することになる。テストが徹底されていなければ、どこで壊れてもおかしくない。その後、React Native Upgrade helper のようなツールが登場して手順はいくらか楽になり、Expo のようなフレームワークもアップグレードを滑らかにするために生まれた。
アップグレードの複雑さ
残念ながら、すべての React Native アプリが理想的な状態にあるわけではない。動きの速い会社では、依存関係を保守しながら機能を届けること自体、バランスを取るのが難しい。その結果、アップグレードは大掛かりな作業になる。Hipcamp も最近、New Architecture + Expo 54 へのアップグレードという難題に直面した。New Architecture のもとでは、数十個のライブラリがすでに古くなっており、アップグレードするか置き換えるしかなかった。
React Native でそれなりの量の仕事をしてきた人なら分かるはずだ。バージョン番号を最新に上げるだけでは、まったく足りない。時間の大半はデバッグと問題解決に消える。しかも複数のライブラリが互いに衝突することがあり、互換性のあるバージョンを見つけ出す必要もある。
幸い、今回はすでに Scout があった——投げられたタスクなら何でも食らいつく AI agent だ。エンジニアがやれば何週間もかかる退屈な依存関係の調査とバージョン調整を、Scout は数日、集中した数セッションで片付けた。内部に Scout のような agent があれば楽ではあるが、Claude Code だけで React Native のアップグレードを完遂する方法も共有しておく。

アップグレード前の Hipcamp アプリの状況
セキュリティアップデートを除けば、アプリのバージョンアップを真面目に追いかけていたわけではなかった。非推奨のパッケージ、4〜5年前、ひどいものは6年前のパッケージがそこら中にある。依存関係は100個以上あり、そのうち約40個は New Arch をサポートするためにアップグレードが必要だった。
そもそも人手が足りておらず、日々のプロダクト開発以外にアップグレードに割く余力はなかった。金の問題ではなく時間の問題だ。何ヶ月もかかるこの大規模アップグレードのために、エンジニアをインパクトのあるプロジェクトから引き剥がす正当化はできなかった。
アップグレードの範囲をどう定めるか
実際にどうやってこのアップグレードを成し遂げたかを掘り下げる前に、このプロセスの核心的な目的に触れておく。これがプロンプトの設計を決めるからだ。
最終的にいくつかの方針を定めた:
-
本当に必要な依存関係だけを扱う
- 現時点で New Architecture / 16kb Android をサポートしていないライブラリだけをアップグレードする
-
依存関係は Expo の対応モジュールで置き換える
- Expo のモジュールはよくメンテナンスされていて信頼でき、利用者も多い。
-
patch-package は最後の手段とする
アップグレードの進め方
次に、このアップグレードをどう進めるかを決めた。結論として、複数のフェーズに分ける必要があった。
各フェーズにどれだけ時間と金を投じるかは、先に考えておくべきだ。最終的に私たちは、token のコストはエンジニアが延々とドキュメントを読み、コードを読み、GitHub issue を調べるよりはるかに安いと気づいた。ましてやエンジニアが浮いた時間は、収益を生むプロダクト機能に使われる。だから予算を理由にこのプロジェクトを制限するなど、検討の俎上にすら上がらなかった。
フェーズ1:agent を構築する
内部に Scout のような agent を構築するか、Expo の upgrade skill をそのまま使うことを強く勧める。コードベースを教え込み、コードベースのアーキテクチャを索引化する仕組みを設計しよう。私たちは documenter コマンド /scout-document-architecture を走らせ、アプリのあらゆる側面を記録するのに1日かけた。これで Scout はハルシネーションを起こさず、何かを見落とすこともない。
フェーズ2:すべての依存関係を監査する
agent に全依存関係の監査タスクを割り当てた。すべてを追跡するには sqlite データベースを使うのがおすすめだ。このデータベースはプロジェクト管理ツールに同期してもいいし、markdown ファイル1つで済ませてもいい。
そしてプロンプトを渡す。以下は当時使っていた例だ:
# Expo SDK 50 → 54 Dependency Audit
Audit every dependency in the app for Expo 50 → 54 upgrade compatibility.
## Context
- **Current:** Expo 50 (RN 0.73, React 18.2)
- **Target:** Expo 54 (RN 0.81, React 19.1)
- Expo 52+ enables New Architecture by default
- Expo 52+ requires 16kb Android page size support
## Research
For each dependency, you MUST:
- **Read GitHub changelogs/releases** between the Expo 50 and Expo 54 compatible versions
- **Search GitHub issues** for bugs, errors, risks, complaints
- **Read setup docs** and migration guides
- **Check for conflicts** with other dependencies in our stack
- **Check if the setup switch is risky or complex**
Then answer:
1. Can this be **replaced with an Expo module**?
2. Can this be **removed entirely**?
3. Are there **known New Arch blockers** in GitHub issues?
4. Are there **16kb page size issues** reported?
5. Does this have **peer dependency conflicts** with other deps?
6. Is the **upgrade path smooth** or does it require code changes?
7. Are there **community complaints** about recent versions?
## Subagent Strategy
- **1 subagent** for small/simple JS-only dependencies
- **5 subagents** for medium/harder native dependencies
- **10 subagents** for extreme-complexity dependencies (react-native core, reanimated, maps, firebase, sentry)
- Each subagent works on exactly ONE dependency — do not batch
## Output
- One notes file per dependency in `./dependencies/{name}.md`
- SQLite DB at `./dependencies.db` with columns: name, expo_50_version, max_version_expo_50, expo_54_version, new_arch_support, sixteenkb_support, status, type (javascript/native), change_recommendation (upgrade/remove/swap), swap_target, complexity (0-10), notes
- **Always prefer replacing with an Expo equivalent library if possible**
- Process dependencies one at a time — do not skip ahead
## References
- https://reactnative.directory/
- https://docs.expo.dev/workflow/upgrading-expo-sdk-walkthrough/
フェーズ3:レビューしてアップグレードを開始する!

その後、各アップグレード項目を人間が1つずつ確認し、問題がないことを確かめた。消すべきでないライブラリを消していないか、代替ライブラリを推薦しているなら適切なものを選んでいるかをチェックする。Expo のライブラリに該当するものがあれば、そのまま使うことを強く勧める。活発にメンテナンスされ、ドキュメントも揃っている。

完了後、各アップグレードの PR を作成する agent を割り当てた。私たちの場合、最初の一巡は3日間ノンストップのアップグレードだった。長時間走るタスクを扱うときは、各ステップに subagent を使うことを強く勧める。依存関係ごとに独自の context を持たせることが、信頼できるアップグレードの鍵だ。
私たちが渡した手順は次のとおり:
依存関係を1つ選ぶ
subagent を割り当て、前のステップのメモを見せる
1〜3個の subagent に指定バージョンへのアップグレードを試させる
完了後、reviewer subagent を割り当てて変更をレビューさせる
yarn lint、tsc、react native bundle を実行し、出たエラーに対処する
ios と android の EAS build を作成し、ビルドが成功することを確認する。起こりうるエラーに対処する
iOS + Android 向けの最終的な EAS Build を作成する
ビルド成果物、手動 QA の手順、影響を受ける画面、その他の関連情報を添えて PR を作成する
戻ってきたときには、レビュー待ちの PR が山ほど溜まっていた。全部を見るのにほとんど時間はかからなかった。もちろん、エンジニアが深く関わる必要のある PR もいくつかあったが、取りかかりは簡単だった。agent が PR の中に context、ドキュメント、関連する GitHub issue などをすべて整理してくれていたからだ。
私たちの経験では、New Architecture のビルド問題のデバッグに費やしたのはわずか 1 週間だった。アップグレード作業は当初見積もっていた 2〜3 か月から数週間に短縮された。四半期が 1 スプリントになった。依存関係の状態はもともとかなりひどかったので、アプリの規模がもっと小さければ、かかる時間はさらに短くなるはずだ。
もちろん細々とした残作業はあるが、山場は越えた。
フェーズ 4:QA、リリース、モニタリング
確実にリリースしたかったので、Hipcamp の同僚全員にこのアプリを使ってもらい、バグを報告してもらうことにした。QA party を開いて、社員が集まってアプリを QA した。この形式は非常に効率がよかった。
その後、iOS と Android の段階的リリース機能を使った。まず iOS を出し、iOS に自信が持ててから Android を出した。
モニタリング:
何らかのエラートラッキングの仕組みは必須で、これが極めて重要だ。加えて、パフォーマンス分析をアプリに組み込むのもよい。こうしたツールは数多くあるが、そのひとつが Expo Observe だ。private preview に参加できたのは幸運だった。
さらに、発生したエラーを agent に継続的に監視させ、修正させた。QA チームから上がってきたものでも本番環境のものでも、agent はエンジニアリングチームがほとんど手を出さずにほとんどのバグを解決した。
意外だったのは、New Architecture で増幅されたメモリ使用量の多さという 1 件を除いて、重大な新規バグがまったく見つからなかったことだ。それどころか、エラーの総数はむしろ減った。理由はこうだと考えている。エンジニアは複雑な問題の解決と十分な QA に時間を使い、残りは agent に任せられるからだ。
結論
AI はエンジニアの働き方を変えつつある。ドキュメントを読み漁り、締め切りに追われ、ニッチな問題のデバッグに費やす時間は、そう遠くないうちに過去のものになるかもしれない。今回のアップグレードで、AI agent は重要かつ難易度の高いプロジェクトにおいて信頼できるパートナーになり得ることが証明された。そして、AI 支援によるエンジニアリングの真価はエンジニアを置き換えることではなく、瑣末な作業に消耗させるのではなく、複雑な問題の解決に集中できるよう解放することにある。