Code from new "expo-*" imports breaks on release versions only

  • In Android release build, any code that calls methods from the new “expo-*” modules simply doesn’t work and throws a “X is not a function” error. (The only way I see the errors is from Sentry)
  • I’m in the process of upgrading to SDK33 from 32 and was about to release.
  • Everything works OK in debug build

Example -

import * as Font from 'expo-font';

...
  _loadResourcesAsync = async () => {
      Font.loadAsync({ 
      ...Entypo.font,
      'Roboto': require('native-base/Fonts/Roboto.ttf') 
  });
});

Sentry shows the following error

TypeError: c.default.loadAsync is not a function. (In 'c.default.loadAsync(F(t),o.localUri)', 'c.default.loadAsync' is undefined)

I can see that the text & icon fonts in the app aren’t loaded.

Similar problems appear on other modules on release builds only

  • expo-permissions - nothing happens when Permissions.askAsync() is called.
  • expo-linear-gradient - no gradient is shown

I can only surmise that the “expo-*” packages just arent’ being included in the bundle for some reason. I have verified that a new bundle is being created after “expo publish” and that it is being copied into the build intermediates folder.

The expo manifest correctly shows expo-font, expo-permissions,etc in the dependency tree.

Any idea what’s going on? Some weird bundling problem?

can you provide a reproducible example?

Solution

I was missing the following lines from android/app/proguard-rules.pro:

-keepclassmembers class * {
  @org.unimodules.core.interfaces.ExpoProp *;
}
-keepclassmembers class * {
  @org.unimodules.core.interfaces.ExpoMethod *;
}

This was also missing but wasn’t causing the issue (I added it anyway, just in case):
-keep class expo.modules** { *; }

I don’t know whether I missed the instructions to add them at some point or if they were missing from the upgrade documentation.