RORK LABEN
BUILD — Rork Max はクラウド上の実機 Mac に Xcode と iOS SDK を載せ、SwiftUI を書き、ビルドし、エラーを読んで直す反復を回します。コードを吐いて終わりではない点が生成物の質に効いていますNATIVE — 生成されるのは React Native ではなく純粋な Swift / SwiftUI です。AR や Metal、ウィジェットなど React Native からは届かない機能に手が届くことが、他ビルダーとの実質的な差になりますPLATFORMS — 対応は iPhone・iPad・Apple Watch・Apple TV・Vision Pro に加えて iMessage まで含みます。ウォッチや拡張から入る設計を試すのに向いていますCOMPANION — Rork Companion により、有料の Apple Developer アカウントなしで生成したアプリを実機の iPhone で確認できます。最初の一本を試す段階の障壁が一段下がりましたPRICING — 無料で開始でき有料プランは月額25ドルから、Rork Max は月額200ドルの Max プランです。回収できる本数と規模を先に見積もっておく価値がありますDEADLINE — Google Play は2026年8月31日以降、新規アプリと更新の双方に対象 API レベル36 以上を要求します。残り10日で、生成物の targetSdkVersion は自分で確認が必要ですBUILD — Rork Max はクラウド上の実機 Mac に Xcode と iOS SDK を載せ、SwiftUI を書き、ビルドし、エラーを読んで直す反復を回します。コードを吐いて終わりではない点が生成物の質に効いていますNATIVE — 生成されるのは React Native ではなく純粋な Swift / SwiftUI です。AR や Metal、ウィジェットなど React Native からは届かない機能に手が届くことが、他ビルダーとの実質的な差になりますPLATFORMS — 対応は iPhone・iPad・Apple Watch・Apple TV・Vision Pro に加えて iMessage まで含みます。ウォッチや拡張から入る設計を試すのに向いていますCOMPANION — Rork Companion により、有料の Apple Developer アカウントなしで生成したアプリを実機の iPhone で確認できます。最初の一本を試す段階の障壁が一段下がりましたPRICING — 無料で開始でき有料プランは月額25ドルから、Rork Max は月額200ドルの Max プランです。回収できる本数と規模を先に見積もっておく価値がありますDEADLINE — Google Play は2026年8月31日以降、新規アプリと更新の双方に対象 API レベル36 以上を要求します。残り10日で、生成物の targetSdkVersion は自分で確認が必要です
記事一覧/開発ツール
開発ツール/2026-08-14中級

Expo SDK 57 に上げる前に、prebuild で消えるネイティブ変更を洗い出す

Expo SDK 57 では expo prebuild が既定で ios と android を消してから再生成します。手編集を上げる前に洗い出す方法、config plugin への移し替え、57.0.9 で解消したメモリ回帰までを実務の順序でまとめました。

Expo SDK 573expo prebuildconfig plugin3React Native227Rork539

壁紙アプリのリポジトリを開いて ios/Podfile の末尾を眺めていたら、自分で書き足した3行が残っていました。いつ足したのか、正直なところ思い出せません。

Expo SDK 57 のリリースノートに目を通したのは、その直後のことでした。目立つ見出しは React Native 0.86 への追随なのですが、実際に手元の作業を変えるのは「その他のハイライト」に一行だけ置かれた項目のほうでした。expo prebuild が、既定でネイティブディレクトリを消してから作り直すようになったのです。

思い出せない3行の行き先を、上げる前に決めておく必要が出てきました。

SDK 57 で本当に効くのは prebuild の一行

Expo SDK 57 のチェンジログを素直に読むと、これは意図して小さくまとめられたリリースです。React Native が 0.85 から 0.86 へ上がり、React は SDK 56 と同じ 19.2 で据え置かれています。Expo チーム自身が「これまでで最も簡単なアップグレード」を目指したと書いています。

とはいえ、0.85 と 0.86 の間には 1,552 ファイルに触れる 601 のコミットがあります。破壊的変更がない想定であっても、取り込むかどうかは意識して決めるべきだ、というのが SDK を分けた理由として説明されています。

変更点手元の作業に効く度合い
React Native 0.85 → 0.86(React は 19.2 据え置き)Android の edge-to-edge 修正や描画まわりの改善。見た目の詰めに効く
expo prebuild が既定で android / ios を消して再生成ネイティブ側に手を入れているなら最優先。--no-clean で従来の挙動
expo@57.0.9 で Hermes V1 のメモリ回帰が解消Reanimated や Worklets を使うアプリは実質必須
開発時の起動が遅くなる回帰(未解決)本番アプリには影響なし。開発の体感だけ
expo-imagewriteToCacheAsync / readFromCacheAsync画像キャッシュを先回りで埋めたいときに使える

3行目は見落とさないでください。SDK 57 の初期リリースは SDK 56 から Hermes V1 のメモリ回帰を引き継いでいて、react-native-workletsreact-native-reanimated を読み込むアプリでメモリ使用量が大きく増える場合がありました。8月13日に出た expo@57.0.9 が React Native 0.86.2 を取り込んで解消しています。

Rork が生成するアプリは、画面遷移やジェスチャの実装でほぼ確実に Reanimated 系に触れています。上げるなら 57.0.9 以上、と最初に決めてしまうのが安全でした。

消えるものを、上げる前に見る

--clean が既定になったことの本質は、挙動の変更というより前提の明文化だと私は受け取りました。Continuous Native Generation は元々「ネイティブディレクトリは生成物であって、原本ではない」という約束の上に立っています。手で編集した瞬間、その約束は破れています。

破れていたことに気づくのが、アップグレードの直後だと痛い。だから上げる前に見ます。

作業用のブランチで、いまのディレクトリの控えを取ってから再生成し、差分だけを読む手順です。

# 1. 作業ブランチを切る
git switch -c chore/sdk57-prebuild-audit
 
# 2. 現状の ios/ を控える(.gitignore している場合でも比較できる)
cp -R ios ../ios-before-sdk57
cp -R android ../android-before-sdk57
 
# 3. 現行 SDK のまま、既定の挙動で作り直す
npx expo prebuild --clean
 
# 4. 差分だけを読む(生成物どうしの比較なので、残るのは自分の痕跡)
diff -ru ../ios-before-sdk57/Podfile ios/Podfile
diff -rq ../ios-before-sdk57 ios | grep -v "Pods\|build\|\.xcworkspace"
diff -ru ../android-before-sdk57/app/src/main/AndroidManifest.xml \
         android/app/src/main/AndroidManifest.xml

Podsbuild を除外しているのは、この2つが依存解決とビルドの副産物で、読んでも判断材料にならないためです。ここを外さないと差分が数千行になり、肝心の3行が埋もれます。

出てきた差分は、3つに仕分けます。

  1. 自分が手で入れた変更 — 移し替えの対象です。ここが本題になります
  2. ライブラリの autolinking が入れたもの — 再生成でも同じものが入ります。放置して構いません
  3. Expo 側のテンプレート更新 — 上げれば新しいほうが入ります。むしろ取り込みたい差分です

私の場合、1に該当したのは Podfile の3行と、Info.plist に足していた写真ライブラリの用途説明でした。どちらも「その場で通したくて手で書いた」類のもので、config plugin に移すべきだったものです。

手編集を config plugin に移す

移し替えは、消える前提のファイルを直接書くのをやめて、生成のたびに同じ変更が入る形に置き換える作業です。プロジェクト直下に plugins/with-native-tweaks.js を1つ置くところから始めました。

// plugins/with-native-tweaks.js
const fs = require('fs');
const path = require('path');
const {
  withInfoPlist,
  withAndroidManifest,
  withDangerousMod,
  AndroidConfig,
} = require('expo/config-plugins');
 
// (1) Info.plist の用途説明を宣言で入れる
const withPhotoLibraryUsage = (config, { message }) =>
  withInfoPlist(config, (config) => {
    config.modResults.NSPhotoLibraryAddUsageDescription = message;
    return config;
  });
 
// (2) AndroidManifest の属性を宣言で入れる
const withManifestAttribute = (config, { name, value }) =>
  withAndroidManifest(config, (config) => {
    const app = AndroidConfig.Manifest.getMainApplicationOrThrow(config.modResults);
    app.$[name] = value;
    return config;
  });
 
// (3) Podfile への追記だけは、ファイルを直接触るしかない
const withPodfileSnippet = (config, { snippet }) =>
  withDangerousMod(config, [
    'ios',
    async (config) => {
      const podfile = path.join(config.modRequest.platformProjectRoot, 'Podfile');
      const contents = fs.readFileSync(podfile, 'utf8');
 
      // 二重追記を防ぐ。prebuild は何度も走るため、冪等性が要ります
      if (contents.includes(snippet.trim())) {
        return config;
      }
 
      fs.writeFileSync(podfile, `${contents}\n${snippet}\n`, 'utf8');
      return config;
    },
  ]);
 
module.exports = (config, props = {}) => {
  config = withPhotoLibraryUsage(config, {
    message: props.photoLibraryMessage ?? '保存した壁紙を写真に書き出すために使用します',
  });
  config = withManifestAttribute(config, {
    name: 'android:largeHeap',
    value: 'true',
  });
  config = withPodfileSnippet(config, {
    snippet: props.podfileSnippet ?? '',
  });
  return config;
};

app.config.ts 側で読み込みます。

export default {
  name: 'Wallpaper',
  slug: 'wallpaper',
  plugins: [
    [
      './plugins/with-native-tweaks',
      {
        photoLibraryMessage: '保存した壁紙を写真に書き出すために使用します',
        podfileSnippet: "post_install do |installer|\n  # プロジェクト固有の後処理\nend",
      },
    ],
  ],
};

書いていて意外だったのは、withDangerousMod の中の冪等チェックが思ったより重要だった点です。prebuild は既定で消してから作り直すため、素直に考えれば毎回まっさらな Podfile に1回だけ追記されるはずです。ところが --no-clean を混ぜて走らせたり、EAS Build 側の環境と手元で挙動が分かれたりすると、同じ行が二度入ることがあります。追記系のプラグインは、必ず「既にあるなら何もしない」を先に書いてください。

withInfoPlistwithAndroidManifest は上書き代入なので、この心配がありません。直接ファイルを触る withDangerousMod は最後の手段として扱い、宣言で書けるものは宣言で書くほうが結果的に安全でした。

移し終えたら、もう一度 npx expo prebuild --clean を走らせて、控えとの差分から自分の痕跡が消えていることを確認します。差分が autolinking とテンプレート更新だけになれば、移行は完了です。

アップグレードの実行順

洗い出しと移し替えが済んでから、ようやく本体を上げます。順序を守るだけで、原因の切り分けがずいぶん楽になりました。

  1. 依存を SDK 57 に揃えるnpx expo install expo@^57.0.0 --fix
  2. バージョンを目で確認するnpm ls expo57.0.9 以上になっているかを見ます。初期リリースのままだと、先ほどのメモリ回帰を踏みます
  3. 健康診断を通すnpx expo-doctor@latest
  4. 旧 SDK 向けに生成した androidios を消す — 残しておく理由がありません。次のビルドで作り直されます
  5. 作り直すnpx expo prebuild。ここで config plugin の効きを確認します
  6. 開発ビルドを作り直すexpo-dev-client を使っているなら、古い開発ビルドは SDK 57 のバンドルを読めません
  7. 実機で確認する — Reanimated を使っている画面のメモリ挙動を、上げる前と比べて見ておくと安心です

3の expo-doctor は、飛ばしたくなりますが飛ばさないでください。依存のバージョン不整合を、実機ビルドの失敗より先に教えてくれます。

なお、開発時の起動が遅くなる回帰は執筆時点で未解決です。本番アプリには影響しないと明記されているので、開発中に「重くなった気がする」と感じても、それが原因の可能性があります。自分のコードを疑い始める前に、既知の回帰を思い出してください。

--no-clean をいつ使うか

逃げ道は用意されています。npx expo prebuild --no-clean で、従来どおり既存のフォルダに変更を当てる挙動に戻せます。

ただ、私はこれを恒久的な運用にはしないと決めました。理由は自分の構成にあります。

壁紙アプリは1つのコードベースから複数本を出し分けていて、app.config.ts と EAS のビルドプロファイルで名前もアイコンも識別子も切り替えています。この構成では ios/ を1つ持ち続けること自体に意味がありません。どのアプリ向けの ios/ なのかが定まらないからです。詳しい組み方はapp.config.ts と EAS で組むホワイトラベル構成にまとめています。

--no-clean が向くのは、移行の途中で「今日中にビルドを通したい」という一時的な場面だと考えています。手編集が残っている状態でアップグレード当日を迎えてしまったとき、その日を凌ぐための道具です。凌いだあとで、消える前提の場所から config plugin へ移す。順序が逆になっただけで、やることは変わりません。

Rork で生成したプロジェクトは、コードを自分で所有できるぶん、手で直す誘惑が常にあります。私も何度も手で直してきました。それ自体は悪いことではないと思っています。ただ、直した場所が生成物なのかどうかだけは、直したその日に判断しておいたほうが、後の自分が楽になります。

今日できる一歩は、アップグレードそのものではなく、prebuild --clean の差分を一度取っておくことです。5分で終わりますし、そこに何も出てこなければ、SDK 57 へのアップグレードは本当に「これまでで最も簡単」なものになります。

私自身まだ移行の途中で、Android 側の差分はこれから読むところです。同じ地点にいる方の手がかりになれば嬉しく思います。お読みいただきありがとうございました。

シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

開発ツール2026-07-28
prebuild --clean で消える手入れを、上げる前に数える — Expo SDK 57 移行の棚卸し
Expo SDK 57 への移行前に、ios/ へ加えた手入れが prebuild の再生成でいくつ失われるかを数える手順をまとめました。素の差分649行のうち意味を持つのは3行。ノイズを正規化して実質的な変更だけを抽出するスクリプトと、config plugin への移し替えを実測つきで共有します。
開発ツール2026-07-30
Renovate が触ってよい依存と、触ってはいけない依存 — Expo SDK 57 の123パッケージを機械的に切り分ける
Rork 生成アプリに依存の自動更新を入れると、Expo が版を管理している123パッケージまで巻き込まれます。2026年7月30日時点の実測では、うち6件が npm の最新版へメジャー更新される差でした。除外リストを手で書かず SDK から機械生成する手順をまとめます。
開発ツール2026-08-10
署名付きURLに変えたらキャッシュが効かなくなった — expo-image のキーを URL から切り離す
署名付きURLは毎回クエリが変わるため、URL をそのままキーにしている限りキャッシュは当たりません。expo-image の writeToCacheAsync / readFromCacheAsync でキーを自分で握り、再ダウンロードを半減させるまでの設計と実測です。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →