HomeGuidesReferenceLearn
ArchiveExpo SnackDiscord and ForumsNewsletter

Add custom native code

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.

Create a local module with the Expo Modules API

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.

Manage custom native projects

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.

Terminal
# 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:

  • Add the plugin to the plugins array in the project's app config.
  • Re-run 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.
  • For complex plugins, consider running npx expo prebuild --clean. This command will delete and re-generate the native directories from scratch.

Manual changes to the native project files

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.

Revert changes from 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.

Develop apps with custom native code

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.

Release apps with custom native code to production

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!

Terminal
# Install the CLI
npm i -g eas-cli

# Build your app!
eas build -p all

Create reusable native modules

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.