I have successfully been able to work inside Expo client after detaching and adding Intercom + OneSignal.
This Canny document a bit the process and also asks the Expo team for a better support of this kind of workflow, as it would certainly make detaching process less scary for many other developers.
If the app is programmed defensively when trying to import/use native libraries that are not part of Expo SDK, it is possible to share the whole JS codebase and make it work fine both in Expo client, and in detached app.
The idea is that in Expo client, the native js calls would simply be ignored/stubbed, while in XCode/Android studio built apps, they would just work fine.
It is possible to import native libraries conditionally with a babel codegen plugin (kentcdodds/babel-plugin-codegen => see screenshot) according to an environment variable. If the app is running in Expo client, I won't import native modules but would simply replace them with undefined, and if the native module is undefined, I would simply not call it (see OneSignal screenshot)
By using such trick and restoring some modifed things in app.json/package.json after ejection (react-native-scripts), I am able to use the exact same codebase for running in Expo client and building with XCode/Android Studio. I just have to toggle an environment variable to switch between Expo and Native.
I think this kind of workflow should be encouraged and supported by the Expo team as it really simplifies life to still be able to use Expo client after ejecting. For sure there are limitations, but most of the time if you just add libraries like Intercom, OneSignal, Segment, Mixpanel, Amplitude or whatever, it's a burden to leave Expo client development workflow completely just for that usecase.
I suggest that:
  • Expo does not necessarily remove the react-native-scripts on eject
  • Expo ejection does generate an exemple of this workflow by adding automatically an example RN library
  • Expo ensures that the Chrome debugger still opens after ejection when running in Expo client (which seems prevented by "app.json->detached" attribute presence)
  • Expo does add a new package.json script to use for running in native mode, for exemple: "dev-native": "EXPO_DETACHED=true exp start --lan",
  • Expo does keep the Expo entry point (which I think triggers the QRCode scanning stuff right?)
This could be a new eject options. I have no idea how to deal with the differences between CRNA and Expo however.