Expo SDK 52 and the Rebirth of React Native Development

By amillionmonkeys
#React Native#Expo#Mobile Development

Why Expo's latest updates convinced us to migrate our 'ejected' React Native apps back to managed workflow. Setup time went from 2 days to 20 minutes.

We ejected from Expo three years ago. Last month, we migrated back. Here's why Expo SDK 52 changed everything.

The Great Ejection of 2021

Like many React Native teams, we hit Expo's walls early. A client needed background geolocation tracking with custom native modules. Another required a specific version of the Google Maps SDK that Expo didn't support. The solution seemed obvious: eject to bare React Native.

"Just eject" became our mantra. We'd get full control over native code, use any library we wanted, and never hit limitations again.

The reality was different. Here's what we actually got:

  • 2-day setup for new developers (installing Xcode, Android Studio, matching SDK versions, debugging build failures)
  • Platform-specific bugs that only appeared on one developer's machine
  • Upgrade nightmares (React Native 0.71 to 0.72 took us three weeks)
  • Build configuration drift between iOS and Android
  • "Works on my machine" became a weekly phrase

We maintained this for three years across five client apps. It worked, but every new project started with 2-3 days of environment setup and configuration copying from the last working project.

What Changed in Expo SDK 52

Expo SDK 52 launched in November 2024, and three things caught our attention:

1. Custom Native Modules in Managed Workflow

Expo's config plugins now handle most native modifications without ejecting. Need to modify AndroidManifest.xml or Info.plist? Write a config plugin. Need a custom native module? Create an Expo module.

The background geolocation feature that forced our original ejection? Now possible with expo-task-manager and expo-location's background mode—no ejection needed.

2. Prebuild: The Best of Both Worlds

The new prebuild system generates native projects on-demand from app.json configuration. You can still access native code when needed, but you don't commit it to git.

Think of it like node_modules for native code. You generate it locally, modify it if needed, but the source of truth is your configuration file.

This solved our "configuration drift" problem. Everyone generates the same native project from the same config.

3. EAS Build and EAS Update

EAS Build runs builds in the cloud with consistent environments. No more "it builds on my machine" issues. No more maintaining Android Studio and Xcode versions across the team.

EAS Update enables over-the-air JavaScript updates without app store reviews. Critical bug fix? Push an update in 10 minutes instead of waiting 2-3 days for App Store review.

The Migration: Ejected Back to Managed

We chose a client project as our test case: a React Native app that we'd ejected two years prior. It had custom native modules, specific build configurations, and was running on React Native 0.71.

Timeline and Process

Day 1: Initial Migration (4 hours)

  1. Installed Expo SDK 52: npx expo install expo@latest
  2. Created app.json from our existing config
  3. Ran npx expo prebuild --clean to generate fresh native projects
  4. Migrated custom native modules to Expo modules

Most surprising moment: The app built on first try. No gradle errors, no CocoaPods issues.

Day 2: Config Plugin Development (3 hours)

We had three custom native configurations:

  • Modified MainActivity.java for deep linking
  • Custom Info.plist entries for location permissions
  • Specific ProGuard rules

Instead of maintaining these as manual edits, we wrote a config plugin that applied them automatically:

// app-config-plugin.js
const { withAndroidManifest, withInfoPlist } = require('@expo/config-plugins');
 
module.exports = function withCustomConfig(config) {
  // Add custom Android config
  config = withAndroidManifest(config, async (config) => {
    // Modify manifest automatically
    return config;
  });
 
  // Add custom iOS config
  config = withInfoPlist(config, async (config) => {
    config.modifiers.infoPlist.NSLocationAlwaysAndWhenInUseUsageDescription =
      "We need your location for delivery tracking";
    return config;
  });
 
  return config;
};

Now these configurations are code, versioned in git, and applied automatically when anyone runs prebuild.

Day 3: EAS Setup (2 hours)

Setting up EAS Build was surprisingly straightforward:

npm install -g eas-cli
eas build:configure
eas build --platform ios
eas build --platform android

Both platforms built successfully in the cloud on first attempt. Our local environment quirks didn't matter anymore.

Total migration time: 9 hours spread over three days.

The 2 Days to 20 Minutes Transformation

Here's the real win. Our old onboarding process for a new developer:

Before (Ejected React Native):

  1. Install Node, Watchman, React Native CLI (30 min)
  2. Install Xcode 14.2 specifically (90 min download + install)
  3. Install Xcode command line tools (10 min)
  4. Install CocoaPods, configure Ruby version (20 min)
  5. Install Android Studio, SDK 33, NDK, configure JAVA_HOME (60 min)
  6. Clone repo, run npm install (10 min)
  7. Run pod install, fix CocoaPods errors (30 min)
  8. Debug first build failures (2-4 hours)
  9. Total: 1.5-2 days

After (Expo Managed):

  1. Install Node (15 min)
  2. Clone repo, run npm install (10 min)
  3. Run npx expo prebuild (5 min)
  4. Run npx expo run:ios or use Expo Go (instant)
  5. Total: 20-30 minutes

For testing JavaScript changes, developers don't even need to build native apps anymore. They use Expo Go on their phone and scan a QR code. Changes appear instantly.

When you do need a native build, EAS Build handles it in the cloud. Junior developers can ship features without ever installing Xcode.

What We Actually Like About Managed Workflow Now

Version Upgrades Became Trivial

React Native 0.71 to 0.72 used to take us three weeks. With Expo SDK 52, we upgraded from SDK 50 to 52 in an afternoon:

npx expo install expo@latest --fix
npx expo-doctor
npx expo prebuild --clean

The expo-doctor command caught incompatible dependencies. The upgrade guide listed breaking changes clearly. No hunting through GitHub issues for obscure build errors.

Consistent Development Environment

Everyone on the team generates the same native code from the same app.json. No more "what version of Gradle are you using?" debugging sessions.

Over-the-Air Updates Are Incredible

We pushed a critical bug fix to production in 12 minutes last week:

eas update --branch production --message "Fix crash on Android 13"

Users got the fix without downloading anything from the app store. This alone justified the migration.

Actually Good Documentation

Expo's docs explain not just what to do, but why. When we hit issues, the error messages were helpful instead of cryptic Gradle stack traces.

What's Still Challenging

Expo SDK 52 isn't perfect. Here are honest limitations:

Library Compatibility

Some React Native libraries still assume you're using bare workflow. If a library requires manual linking or native code changes without a config plugin, you'll need to create a custom plugin or wait for library support.

We had to write a config plugin for one analytics library. It took 2 hours but now works automatically for everyone.

Large App Size

Expo apps are slightly larger because they include modules you might not use. Our app went from 42MB to 47MB on iOS. For most projects, this doesn't matter, but if you're optimizing for emerging markets with slow connections, it's worth considering.

Learning Curve for Config Plugins

If you need custom native configuration, you'll learn about config plugins. They're powerful but require understanding how Expo modifies native projects. Budget time for learning.

Should You Migrate Back to Managed?

If you ejected from Expo before 2024, it's worth reconsidering. Expo SDK 52 solves most reasons we ejected:

Migrate if:

  • You want faster onboarding for new developers
  • You're tired of maintaining native build configurations
  • You want over-the-air updates
  • You spend too much time on React Native upgrades

Stay ejected if:

  • You have deeply custom native code that can't be handled by config plugins
  • You need absolute control over every native dependency version
  • Your app requires bleeding-edge native features not yet in Expo

For us, the decision was clear. The time saved on environment setup, upgrades, and deployments far outweighed the slight reduction in control.

Getting Started

If you're considering migrating back to managed workflow:

  1. Read the Expo prebuild docs
  2. Test on a non-critical project first
  3. Budget time for config plugin development if you have custom native code
  4. Set up EAS Build to avoid local environment issues
  5. Check compatibility with your existing libraries

We're now migrating our remaining three ejected apps to Expo SDK 52. Each migration goes faster as we build reusable config plugins and understand the workflow better.

Conclusion

Three years ago, we ejected from Expo because it felt limiting. Today, we're migrating back because Expo SDK 52 solved the problems that forced us out.

Our new developer onboarding went from 2 days to 20 minutes. React Native upgrades went from weeks to hours. We can push critical fixes without app store review.

The landscape of React Native development changed. If you ejected years ago, it's worth another look.


Building a React Native app or considering Expo for your next project? We've now migrated four production apps and learned all the gotcas. Get in touch to discuss how Expo's managed workflow could work for your project.

T: 07512 944360 | E: [email protected]

© 2025 amillionmonkeys ltd. All rights reserved.