Skip to content
useffect.sh
Book 30 min with a senior
Native

Expo Modules API

Expo’s API for writing native modules and views in Swift and Kotlin with one shared DSL, with no Objective-C or bridge boilerplate.

Definition

The Expo Modules API is the API provided by expo-modules-core for writing native modules and native views in Swift on iOS and Kotlin on Android, with a module definition that reads the same on both platforms. A module declares its name, its sync or async functions, its events, and its views in a DSL (Name, Function, AsyncFunction, Events, View), and expo-modules-core handles type conversion and exposure to JavaScript through JSI. It replaces writing a classic Native Module in Objective-C and Java with its macros and boilerplate, and is an alternative to React Native’s Turbo Modules with a shorter learning curve. It works on the New Architecture and stays compatible with apps still on the old one. Since SDK 58, a 2.0 version in beta lets you annotate a plain Swift or Kotlin class instead of using the DSL. You meet it as soon as you write a custom module or read the source of any Expo SDK package.

In a real app

An Expo module is created with npx create-expo-module, or locally inside the project with npx create-expo-module --local, which puts it under modules/. It is described by an expo-module.config.json file at its root listing platforms and module classes; that file is what Expo’s autolinking reads, independently of the React Native CLI autolinking. iOS code is Swift (a Module subclass with a definition block), Android code is Kotlin, and JavaScript loads the module with requireNativeModule.

Choosing between Expo Modules, Turbo Modules, and Nitro comes down to what you are writing: shared C++, pick Turbo Modules; very frequent latency-sensitive calls (frame processing, heavy synchronous reads), Nitro; ordinary native access with little boilerplate, the Expo Modules API. The Expo docs state performance comparable to Turbo Modules, since both go through JSI, and the Android microbenchmarks published with SDK 58 even put Expo Modules 2.0 ahead of a Turbo Module in all twelve cases measured. The price of entry is a dependency on the expo package and a few hundred kilobytes in the binary.

Expo Modules 2.0, in beta on iOS and Android in SDK 58 after an experimental iOS macros phase in SDK 57, replaces the DSL with annotations on a plain Swift or Kotlin class. Expo reports synchronous calls 2.5 to 5.6 times faster than the DSL on iOS. The JavaScript contract does not change, so you can migrate one module at a time.

Sources

All 35 glossary terms

One of these is blocking your app?

30 minutes with a senior to look at the problem in your code. Free.