How does upgrading the Expo SDK differ between a project using Continuous Native Generation and one that commits its native folders?
answer
- new SDK, new template
- regenerate instead of merging
- delete stale ios and android
- native upgrade helper for committed folders
- plugins must support the new SDK
basics
~20 sWith CNG you bump expo and its packages, then regenerate the native folders from the new SDK's template. With committed native folders you must apply the native template changes yourself, using Expo's native upgrade helper, then reinstall pods.
solid answer
~40 sBoth start the same way: install the new `expo` version, align the other packages with `npx expo install --fix`, and run `npx expo-doctor`. They diverge at the native step. Under CNG you delete any `ios/` and `android/` generated for the old SDK and regenerate them; since SDK 57 a plain `npx expo prebuild` clears and recreates them, and EAS Build generates them fresh anyway. The new template carries the native changes, so there is nothing to merge. With committed native folders there is no regeneration: you apply the relevant template changes by hand using Expo's native project upgrade helper, run `npx pod-install`, and resolve conflicts with your own edits. The CNG risk shifts to config plugins, which must support the new SDK or be updated.
go deeper
Recall that under CNG you upgrade packages and regenerate the native folders instead of editing them.
Explain the shared JavaScript steps and the two native paths: regeneration versus merging template changes with the upgrade helper.
Show where CNG upgrades still fail: stale folders, lagging plugins, team-owned native modules, and why the result ships as a store build.
Use upgrade cost as an input to the workflow decision: what the team saves by regenerating, and what it now owns as plugin code.
## Why native upgrades are the hard part Each Expo SDK pins a React Native version, and each React Native release changes the native projects: Gradle and Kotlin versions, `AppDelegate` and `MainApplication` code, Podfile helpers, minimum OS versions. In a project that owns its native folders, every one of those changes must be merged by hand into files that also carry the team's own edits. That merge is the classic pain of React Native upgrades. ## The shared steps 1. **Install the new `expo` version**, for example `expo@^57.0.0` for SDK 57. 2. **Align dependencies** with `npx expo install --fix`, which moves Expo and community packages to versions compatible with that SDK. 3. **Run `npx expo-doctor`** to catch known problems. 4. **Read the SDK release notes** for breaking JavaScript changes. ## The native step, two ways | | CNG (generated folders) | Committed native folders | |---|---|---| | Native template changes | arrive with the new template | merged by hand | | Tool | `npx expo prebuild`, or EAS Build | Expo's native project upgrade helper | | Your own native edits | live in config plugins, re-applied automatically | must be preserved through the merge | | Pods | installed by prebuild | `npx pod-install` | | Typical risk | a plugin not yet updated for the SDK | a missed or mis-merged template change | **With CNG**, delete the `ios/` and `android/` folders you generated for the old SDK and regenerate. Since SDK 57, a plain `npx expo prebuild` already deletes and recreates them; `npx expo run:ios` would **not**, because it only prebuilds when the folder is missing. EAS Build regenerates from scratch for a project whose native folders are gitignored. **With committed folders**, open the upgrade helper for your from and to versions, apply each relevant change to your native files, reinstall pods and rebuild. Every hand customisation is a potential conflict. ## Where CNG upgrades still go wrong - **Config plugins lag behind**: a plugin that edits native files assuming the old template may fail or silently do nothing on the new one. Check plugin compatibility before upgrading. - **Stale local folders**: someone runs `run:android` against an old `android/` and reports a bug that the new template would not have. - **Leftover `--no-clean` habits**: layering the new SDK's config onto old folders mixes old template files with new configuration. - **Native code outside plugins**: any local native module or plugin written by the team is now part of the upgrade surface and needs its own testing. ## A worked sequence for an SDK 56 to 57 upgrade under CNG 1. Upgrade `expo`, run `npx expo install --fix` and `npx expo-doctor`. 2. Check that every entry in `plugins` supports SDK 57. 3. Run `npx expo prebuild` (clean by default in 57) and build both platforms locally. 4. Run the test suite and a development build on devices. 5. Ship through a store build: an SDK upgrade changes native code, so it cannot go out as an over-the-air update to old binaries. ## What this means for the choice of workflow Upgrade effort is the strongest practical argument for CNG: the team maintains a list of inputs rather than two native projects. The price is that every native customisation must be expressible as a package or plugin, and plugins become code the team upgrades too. ## Keeping local folders honest during an upgrade The riskiest artifact in a CNG upgrade is an old native folder on someone's machine. A few habits prevent it: - Announce the upgrade and ask everyone to delete `ios/` and `android/` after pulling it; they are gitignored, so git will not do it for them. - Prefer `npx expo prebuild` over `run:*` for the first build after pulling, because only prebuild regenerates an existing folder. - Rebuild development builds for the team, since a development client compiled for the old SDK cannot load JavaScript that expects the new native code. - Keep the upgrade in its own pull request, so a regression can be traced to the SDK rather than to feature work landing alongside it.
- After an Expo SDK upgrade in a CNG project, why is npx expo run:android not enough to pick up the new template?`run:android` prebuilds only when `android/` is missing. If an old folder exists, it builds that, with the previous SDK's template. Delete the folder or run `npx expo prebuild` (clean by default since SDK 57) first.
- What does a team with committed native folders use to see native changes between SDK versions?Expo's native project upgrade helper, which shows the template differences between two SDK versions. The team applies the relevant changes by hand, runs `npx pod-install`, and keeps its own native edits intact through the merge.
saying these in an interview costs you the question
- An SDK upgrade can ship to existing users as an over-the-air update
- CNG upgrades need the native upgrade helper too
- npx expo run:ios regenerates an existing ios folder for the new SDK
- Config plugins never need attention during an SDK upgrade
- Committed native folders upgrade automatically with the expo package