Difference between ExpoKit and React Native project

ExpoKit is kind of a hybrid between "pure JS" Expo apps and "vanilla" React Native. At its core it's still a React Native project, but a few things differ about the build system, developer experience, and features available.

Features

As of today, most of the APIs in Expo's SDK are not available in a vanilla React Native project, but they are available in ExpoKit. We think this might change in the future, but it'll be a lot of work.

Expo's push notification service does not currently work in ExpoKit, nor for vanilla React Native.

Build System

Both vanilla RN apps and ExpoKit apps use Xcode and Android Studio to build the native code. iOS ExpoKit apps use CocoaPods to install dependencies, which can add a little bit of complexity to managing the native build. Android ExpoKit apps have additional Gradle configuration to build multiple versions of React Native into the same binary (this is used to enable over-the-air updates of multiple SDK versions of JS), which can sometimes increase the complexity of adding other React Native libraries.

The JavaScript for an ExpoKit and React Native project is built by Metro, although in ExpoKit you need to run Metro using Expo's XDE or exp tools so that they can handle extra configuration for the project. This means you run a command like exp start rather than react-native run-android.

Due to the current design of ExpoKit (although this may change in the future), some open source React Native libraries may have compatibility issues with ExpoKit. For example, if a native library expects to be able to request a reference to React Native's OkHttp instance on Android, there may be a type mismatch when running inside ExpoKit due to the namespacing Expo uses to allow multiple versions of React Native to compile. That said, these issues tend to be pretty rare, and we're working on a few different ways for ExpoKit to be more and more compatible with libraries in the ecosystem.

This multi-version support also means that ExpoKit binaries tend to be larger than corresponding vanilla React Native binaries, although that may change in the future.

Your subquestions

  1. Some developers prefer to manage how their JS bundles and assets are distributed themselves, or they may need a library which isn't currently compatible with ExpoKit. Binary size is another reason why you may prefer vanilla RN.
  2. It's not currently possible to use most Expo APIs in a React Native project. Some APIs available in the Expo SDK are bundled from open source projects (such as react-native-maps) and can be used with a vanilla RN project.
  3. I'm not sure how to parse this question -- Expo APIs are currently just React Native APIs which know how to talk to each other and make certain assumptions about the environment they're running in.

Question from comment 1: You can modify the ExpoKit build all you want, although it may make it slightly harder to upgrade to a newer SDK release depending on how heavily you edit it.