expo / router

[ARCHIVE]: Expo Router has moved to expo/expo -- The File-based router for universal React Native apps
https://docs.expo.dev/routing/introduction/
1.36k stars 113 forks source link

Template tabs@48 is broken #853

Open durasj opened 1 year ago

durasj commented 1 year ago

Which package manager are you using? (Yarn is recommended)

yarn

Summary

When we build a production IPA for iOS, the app crashes instantly with Invariant Violation: TurboModuleRegistry.getEnforcing(...): 'DevSettings' could not be found.:

default 17:06:14.420437+0200    test48  Not internal release, disabling SIRL
default 17:06:14.420512+0200    test48  Adding securityd connection to pool, total now 1\
error   17:06:14.427999+0200    test48  Invariant Violation: TurboModuleRegistry.getEnforcing(...): 'DevSettings' could not be found. Verify that a module by this name is registered in the native binary., js engine: hermes
error   17:06:14.429765+0200    test48  Invariant Violation: "main" has not been registered. This can happen if:
* Metro (the local dev server) is run from the wrong folder. Check if Metro is running, stop it and restart it in the current project.
* A module failed to load due to an error and `AppRegistry.registerComponent` wasn't called., js engine: hermes
error   17:06:14.429812+0200    test48  Unable to find module for RedBox
error   17:06:14.429861+0200    test48  Unhandled JS Exception: Invariant Violation: TurboModuleRegistry.getEnforcing(...): 'DevSettings' could not be found. Verify that a module by this name is registered in the native binary., js engine: hermes
default 17:06:14.431931+0200    test48  *** Terminating app due to uncaught exception 'RCTFatalException: Unhandled JS Exception: Invariant Violation: TurboModuleRegistry.getEnforcing(...): 'DevSettings' could not be found. Verify that a module by this name is registered in the native binary., js engine: hermes', reason: 'Unhandled JS Exception: Invariant Violation: TurboModuleRegistry.getEnforcing(...): 'DevSettings' could not be found. Verify that a module by this name is registered in the na..., stack:
invariant@1453:25
getEnforcing@1431:27
anonymous@38522:49
loadModuleImplementation@150:13
guardedLoadModule@88:37
metroRequire@37:91
anonymous@38505:61
loadModuleImplementation@150:13
guardedLoadModule@88:37
metroRequire@37:91
anonymous@41007:31
loadModuleImplementation@150:13
guardedLoadModule@88:37
metroRequire@37:91
anonymous@40999:30
loadModuleImplementation@150:13
guardedLoadModule@88:37
metroRequire@37:91
anonymous@40977:47
loadModuleImplementation@150:13
guardedLoadModule@88:37
metroRequire@37:91
anonymous@40942:32
loadModuleImplem<…>

The same exact error occurs on a fresh tabs@48 template with zero changes. We can reproduce this on two completely different Apple devices - one Mac mini and one MacBook Air.

It works fine in dev client mode with Expo Go. It also works fine on Android, with an empty 48 expo template (so no router) and tabs@49. And no, unfortunately, we can't switch to v2 with SDK 49 yet.

Minimal reproducible example

  1. Clone https://github.com/durasj/expo-router-48-broken-reproduce.
  2. Run yarn install.
  3. Create a production build, so, for example, run eas build --platform ios --profile preview --local to get an IPA to run on a device and try to open it.
durasj commented 1 year ago

After a ton of trial & error, I narrowed it down to these two lines from expo-router:

https://github.com/expo/router/blob/expo-router%401.7.7/packages/expo-router/entry.js#L3,L7

import "@expo/metro-runtime";

// This file should only import and register the root. No components or exports
// should be added here.
import { renderRootComponent } from "expo-router/src/renderRootComponent";

If I make my own entry file and drop those two, it works. Of course, I have to switch to import { registerRootComponent } from 'expo';.

zRelux commented 12 months ago

@durasj Can you explain the solution a bit further?

durasj commented 12 months ago

@zRelux In your index.js, don't import expo-router/entry. Instead, do:

const { App } = require('expo-router/_app');
registerRootComponent(App);

Ideally, only in production (!__DEV__), though, as their entry file has some additional logic that is especially helpful during the development.