React Native Advanced: Performance, Native Code and Releasing
Native Code and Development Builds
In this lesson you will
- Explain when Expo Go is enough and when you need a development build
- Describe Continuous Native Generation, prebuild and config plugins
- Configure an app in app.config.ts and explain what native modules are
Introduction
So far you have run your app inside Expo Go, a ready-made app on your phone that loads your JavaScript. It is wonderful for learning and prototyping. But Expo Go is one fixed app with a fixed set of native code inside it. The moment you need a library with its own native code, or want to change something deep, such as your app's name on the home screen, its icon or its permissions, you need your own app. That is a development build.
What is native code?
Your React Native app has two halves:
- JavaScript (TypeScript): your screens and logic, which Fast Refresh updates instantly.
- Native code: the Swift or Objective-C and Kotlin or Java projects that make the actual iPhone and Android app, including the code that talks to the camera, GPS and other hardware.
Most apps are 99 percent JavaScript. Native code only changes when you add a library that includes it, change app settings such as permissions, or upgrade the SDK.
Expo Go versus a development build
The Expo docs describe a development build as "your own version of Expo Go" in which you can "use any native libraries and change any native configuration." In practice:
| Expo Go | Development build | |
|---|---|---|
| Set-up | Install from the store, scan a QR code | Build once for your project |
| Native libraries | Only those inside Expo Go | Any library, including your own |
| App name, icon, permissions | Fixed | Yours |
| Best for | Learning, quick prototypes | Real apps heading to the stores |
You still get Fast Refresh. You only rebuild when native code changes.
Quick quiz
Which of these needs a development build instead of Expo Go?
Making a development build
Install the development client, then build in one of two ways:
Terminal
npx expo install expo-dev-client- On your computer (needs Xcode for iPhone on a Mac, and Android Studio for Android):
Terminal
npx expo run:android
npx expo run:ios- In the cloud with EAS Build (needs an Expo account and no native tools installed):
Terminal
eas build --platform android --profile development
eas build --platform ios --profile developmentThen start the development server as usual with npx expo start, and open the build you installed instead of Expo Go.
Where are the android and ios folders?
A new Expo project has no android and ios folders at all. Expo uses Continuous Native Generation, or CNG: the native projects are not something you maintain by hand. They are generated from your configuration when needed. The docs describe them as "short-lived native projects" generated "only when needed."
The command that generates them is prebuild:
Terminal
npx expo prebuildIt creates the android and ios folders from a template that matches your Expo SDK version. Running it again with --clean deletes and regenerates them, which the docs call the safest option in most cases. Build commands such as npx expo run:android run prebuild for you when the folders are missing.
The rule that follows: do not hand-edit the generated folders. The docs warn that you risk losing changes the next time you prebuild with --clean. New projects add the folders to .gitignore. If you need native changes, you describe them in configuration instead, so they can always be regenerated.
Configuration: app.json and app.config.ts
Your app's identity and native settings live in app.json, or in app.config.ts if you want to compute values with code. The TypeScript version gets type checking:
nameis what people see under the icon.slugis the project's short name.bundleIdentifier(iPhone) andpackage(Android) are the app's permanent unique ID, written like a reversed web address. Pick it carefully, because it cannot change after you publish.pluginslist config plugins.
Config plugins
A config plugin is a function that changes the native projects while they are being generated. The docs define them as "functions that perform modifications on native projects during prebuild." Most Expo libraries ship a plugin, and you give it options. In the example, the camera plugin writes your reason text into the iPhone's permission settings, which is exactly the explanation you learned to provide in the device features lesson.
This is how you customise native behaviour without ever opening Xcode or Android Studio, and why you can throw the native folders away and rebuild them at any time.
Quick quiz
Why should you not hand-edit the generated android and ios folders?
Native modules and the New Architecture
Sometimes no library does what you need, so you write native code and expose it to JavaScript. That is a native module. Two ways exist:
- The Expo Modules API lets you write the module in Swift and Kotlin with a friendly structure, and is what most Expo libraries use.
- A TurboModule is the lower-level React Native way, part of the New Architecture.
What makes both fast is JSI, the JavaScript Interface. The React Native docs explain it as "an interface that allows JavaScript to hold a reference to a C++ object and vice-versa," so methods can be called directly "without serialization costs", instead of through the old asynchronous bridge. Fabric is the new renderer built on the same foundation. You rarely touch these directly, but now you know why modern React Native is more responsive, and what an error message is talking about when it mentions them.
A word on cost and complexity
Native code adds work: slower builds, more tools to install and more things that can differ between phones. A good rule is to stay in JavaScript, and in Expo's ready-made libraries, for as long as you can. When you do need a development build, CNG keeps it manageable, because the native side stays small, generated and reproducible.
Try it yourself
Create an app.config.ts for your project with a name, bundleIdentifier and package. Install expo-dev-client, then create a development build for one platform, either with npx expo run:android or in the cloud with EAS Build. Run npx expo prebuild --clean and look at what appears in the new folders, then remember that you should not edit them.
Summary
- Expo Go is a fixed app for learning. A development build is your own app that can use any native library and change native settings.
- With Continuous Native Generation the
androidandiosfolders are generated bynpx expo prebuildfrom your config, so do not hand-edit them. - Describe app identity and native settings in
app.config.tsand config plugins, and write native modules only when no library does the job.
Lesson complete
+20 XP
Nice work. Keep going while it is fresh.