Hello, I created a project through Expo, through the instructions Onesignal is installed in it, the problem is that when I execute expo run:ios everything works correctly and I see pushid in the logs, but if I do expo build:ios the application cannot start and in the mac console I see the error “Invariant Violation: Your JavaScript code tried to access a native module that doesn’t exist in this development client.”
I suppose that during build, for some reason, native modules are not installed, please tell me how this can be fixed.
Hi @wizard31337
TL;DR: Build with EAS Build instead of expo build
.
There are two ways to build an Expo app:
- The “Classic”
expo build:ios
/expo build:android
- The new
eas build
The classic build system does not support dependencies that require native code )other than whatever is part of the Expo SDK). Since the Onesignal SDK is not part of the Expo SDK, you can’t use expo build
to build your app. You will also not be able to use the Expo Go app to develop/test your app (unless you’re careful to avoid calling Onesignal in _DEV_
mode.)
With EAS Build, all of your dependencies are compiled into your app, including any with custom native code, like Onesignal. Also, any parts of the Expo SDK that you have not installed as dependencies will not be built into your app. This is the power of EAS Build. Your app will be smaller than if you built it with expo build
, and you can install things that would previously required you to eject.
Instead of using the Expo Go app for development/testing you can build a Custom Dev Client. The onesignal-expo-plugin
documentation has a link to the blog post that introduced custom clients. See also the documentation. A custom dev client is basically like a customised version of Expo Go that includes all of and only your dependencies. You can use it like you would Expo Go.
One thing to keep in mind: expo run
generates native code (ios
and android
directories) in your app. At that point you have pretty much got a plain React Native app instead of a “managed” Expo app.
At this point you have a couple of options depending on whether you want to make your own changes to the native projects:
If you want to write your own custom native code
You would proceed like you would for a normal React Native app. You can still build with EAS Build and you can still use OTA Updates and Expo push notifications etc. but you need to manage all of the native code yourself and e.g. if you change the icon in app.json
then it will not have any effect on your app. You'll need to change the icon in the native projects like you would for a React Native app. If you use expo prebuild
it will probably make the necessary changes, but there's a possibility that it will somehow conflict with your custom changes. If you run expo prebuild --clean
it will delete and regenerate the ios
and android
directories, wiping out your custom changes.
If you do not need to make your own custom changes to the native code under ios
and android
You have two options:
- Ignore the
ios
andandroid
directories (you can add them to .gitignore) and useexpo prebuild --clean
to regenerate them if you make changes toapp.json
. - Delete the
ios
andandroid
directories (e.g. by checking out a commit from before you ranexpo prebuild
/expo run
or by following the procedure here)
Personally, I avoid running expo run
and instead build a custom dev client or build using eas build
or eas build --local
.
If I am writing my own Config Plugin for a package that doesn’t already come with one I use expo prebuild
for testing the config plugin, but afterwards I immediately remove the ios
and android
directories and revert the changes to .gitignore
, package.json
, yarn.lock
etc.