Learn how to add custom native code to your Expo project.
Expo projects can use both third-party React Native libraries with native code and your own custom native code. Creating a development build allows you to include your specific native dependencies and customizations and not what's in the latest Expo SDK. These native customizations can be any React Native library or your own custom native code.
For most third-party native libraries, autolinking makes it easy. All you have to do is install the package and create a new development build to use the module. Some modules might also need a config-plugin for additional native customizations. When adding your own custom native code, the approach varies based on how you want to work with native code.
By default, Expo projects use Continuous Native Generation (CNG). This means that projects do not have android and ios directories containing the native code and configuration. Instead, the native directories are generated right before building the app and is based on your app config and native modules in package.json. This simplifies the management and upgrading of native code.
It might seem you cannot add custom native code to a project using CNG. However, you can still add that by creating a local Expo module.
Local Expo Modules function similarly to Expo Modules used by library developers and within the Expo SDK. They are not published to npm. Instead, you create them directly inside your project.
Creating a local module allows you to write custom Swift and Kotlin code that you can interact with from your JavaScript code. It is also included in the development builds and production apps automatically when you build with EAS Build or when you compile your app locally.
You can opt out of CNG and directly manage the code and configuration inside your android and ios directories. To generate these directories, run npx expo prebuild
or compile your app locally (npx expo run android
or npx expo run ios
). You can also create a development build before compiling your app locally. To do so, run npx expo install expo-dev-client
before prebuild
or run
.
# Build your native Android project
-
npx expo run:android
# Build your native iOS project
-
npx expo run:ios
npx expo run:android
requires Android Studio and the Android SDK to be installed. See how to setup environment.npx expo run:ios
requires Xcode (macOS only) installed on your computer. See how to setup environment.The run
commands will prebuild your project to generate all the native code within your project directory. If you manually modify the android or ios directory, you cannot re-run npx expo prebuild
safely, as this may overwrite your changes.
If you install a library with Expo config plugin, you'll need to follow a few steps:
plugins
array in the project's app config.npx expo prebuild
to sync the changes before rebuilding the native app. This process often involves tasks like adding required permissions to the AndroidManifest.xml or Info.plist.npx expo prebuild --clean
. This command will delete and re-generate the native directories from scratch.If you manually modify the android and ios directories, you must set up new libraries manually. Running npx expo prebuild
may not work as expected because the project is now in an unpredictable state (think of this like running yarn
after manually modifying your node_modules directory).
If you want to make static changes to your native project files, such as AndroidManifest.xml or Info.plist, and still have access to prebuilding, then create a config plugin to see how you can hook into the prebuild process to make those changes.
npx expo run:[android|ios]
Suppose you have decided to roll your app back to being fully managed (no android or ios directories in your project directory). In that case, you can check out your most recent commit before executing npx expo run:[android|ios]
, then run npm install
again to restore the state of your node_modules directory.
Once you have customized the native code in your project, you can use the expo-dev-client
library to create a development build and retain the convenience of working with JavaScript or TypeScript in Expo Go. You can create a development build for your managed or bare workflow.
When you're ready to ship your app, you can build it with EAS Build the same as you were building it before adding custom native code. Alternatively, you can archive and sign it locally. Unsurprisingly, we recommend EAS Build!
# Install the CLI
-
npm i -g eas-cli
# Build your app!
-
eas build -p all
Apart from adding custom native code to a project, the Expo Modules API enables developers to build reusable modules for Expo and React Native projects using Swift, Kotlin, and TypeScript. These modules are often published to npm. They can also be included as separate packages within a monorepo. We use the Expo Modules API for most modules in the Expo SDK.
Another option is to use React Native's Core Native Modules API, which may require some C++ knowledge in addition to Objective-C and Java. Most React Native modules in the ecosystem are built using this API because it is and always has been part of React Native. The Expo Module API is new and intends to solve many of the pain points of using the core API.