I am working with the default typescript template generated from the mand line npx create-expo-app -t expo-template-blank-typescript
and I get this error when I try to start the project.
The main reason I think, is because I am working in a monorepo.
The entry point in package.json points to "main": "node_modules/expo/AppEntry.js"
but in a monorepo, the expo module is only present in the parent node_modules
folder.
What I have tried
I have tried setting up the entry point in app.json to: ./src/App.tsx
, ./dist/App.js
with no success
When I change the main field of package.json to ../../node_modules/expo/AppEntry.ts
I got this error:
Invariant Violation: Failed to call into JavaScript module method AppRegistry.runApplication(). Module has not been registered as callable. Registered callable JavaScript modules (n = 11)
My setup
I am working with turborepo. My folder structure look like
├── app
│ ├──project1
│ │ ├── package.json
│ │ ├── App.tsx
│ │ ├── app.json
│ │ └── tsconfig.json
│ └──node_modules
└── node_modules
└── expo
└── AppEntry.js
Is there a clean way to handle this scenario ?
I am working with the default typescript template generated from the mand line npx create-expo-app -t expo-template-blank-typescript
and I get this error when I try to start the project.
The main reason I think, is because I am working in a monorepo.
The entry point in package.json points to "main": "node_modules/expo/AppEntry.js"
but in a monorepo, the expo module is only present in the parent node_modules
folder.
What I have tried
I have tried setting up the entry point in app.json to: ./src/App.tsx
, ./dist/App.js
with no success
When I change the main field of package.json to ../../node_modules/expo/AppEntry.ts
I got this error:
Invariant Violation: Failed to call into JavaScript module method AppRegistry.runApplication(). Module has not been registered as callable. Registered callable JavaScript modules (n = 11)
My setup
I am working with turborepo. My folder structure look like
├── app
│ ├──project1
│ │ ├── package.json
│ │ ├── App.tsx
│ │ ├── app.json
│ │ └── tsconfig.json
│ └──node_modules
└── node_modules
└── expo
└── AppEntry.js
Is there a clean way to handle this scenario ?
Share Improve this question edited Dec 21, 2022 at 9:27 TOPKAT asked Dec 20, 2022 at 10:38 TOPKATTOPKAT 8,7783 gold badges62 silver badges87 bronze badges1 Answer
Reset to default 5I finally found the answer here:
https://docs.expo.dev/guides/monorepos/
You need to override metro config:
There are three main changes we need to:
- Make sure Metro is watching the full monorepo, not just apps/cool-app.
- Tell Metro where it can resolve packages. They might be installed in apps/cool-app/node_modules or node_modules.
- Force Metro to only resolve (sub)packages from the nodeModulesPaths.
We can configure this by creating a metro.config.js with the following content:
const { getDefaultConfig } = require('expo/metro-config');
const path = require('path');
// Find the project and workspace directories
const projectRoot = __dirname;
// This can be replaced with `find-yarn-workspace-root`
const workspaceRoot = path.resolve(projectRoot, '../..');
const config = getDefaultConfig(projectRoot);
// 1. Watch all files within the monorepo
config.watchFolders = [workspaceRoot];
// 2. Let Metro know where to resolve packages and in what order
config.resolver.nodeModulesPaths = [
path.resolve(projectRoot, 'node_modules'),
path.resolve(workspaceRoot, 'node_modules'),
];
// 3. Force Metro to resolve (sub)dependencies only from the `nodeModulesPaths`
config.resolver.disableHierarchicalLookup = true;
module.exports = config;
AND
Change the default entry point in index.js
import { registerRootComponent } from 'expo';
import App from './App';
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
// It also ensures that whether you load the app in Expo Go or in a native build,
// the environment is set up appropriately
registerRootComponent(App);