Overview
Monorepos allow you to manage multiple packages in a single repository. This is useful for sharing code between your Expo app, web app, and shared packages.Common Monorepo Structure
Setup with Yarn Workspaces
1
Initialize the monorepo
2
Configure workspaces
package.json
3
Create the Expo app
apps/mobile/package.json:4
Create shared packages
packages/ui/package.json
5
Link packages
In Then run:
apps/mobile/package.json:Setup with pnpm
1
Initialize with pnpm
2
Create pnpm-workspace.yaml
pnpm-workspace.yaml
3
Configure .npmrc
.npmrc
React Native and Expo require hoisting due to their native module resolution.
4
Install dependencies
Setup with npm Workspaces
package.json
Metro Configuration
Configure Metro for monorepos
apps/mobile/metro.config.js
For Yarn 2+ (Berry)
apps/mobile/metro.config.js
TypeScript Configuration
Root tsconfig.json
tsconfig.json
App-specific tsconfig
apps/mobile/tsconfig.json
Package tsconfig
packages/ui/tsconfig.json
Shared Package Examples
UI Component Package
packages/ui/src/Button.tsx
packages/ui/src/index.ts
API Client Package
packages/api/src/client.ts
Shared Config Package
packages/config/src/theme.ts
Using Shared Packages
apps/mobile/app/index.tsx
Running Commands
- Yarn
- pnpm
- npm
EAS Build Configuration
apps/mobile/eas.json
.easignore
Prevent uploading unnecessary files:apps/mobile/.easignore
Troubleshooting
Metro can't find modules from workspace packages
Metro can't find modules from workspace packages
Ensure your Clear Metro cache:
metro.config.js is configured correctly:Native modules not working
Native modules not working
Native modules must be installed in the app’s node_modules:Or hoist with pnpm:
.npmrc
EAS Build fails with workspace packages
EAS Build fails with workspace packages
Ensure
.easignore doesn’t exclude workspace packages:Best Practices
- Hoist React Native dependencies: Use hoisting patterns to avoid duplicate native modules
- Use workspace protocol: Reference local packages with
"@my-app/ui": "*"or"workspace:*" - Share configs: Keep ESLint, Prettier, and TypeScript configs in shared packages
- Version together: Use tools like Changesets for coordinated versioning
- Clear caches frequently: Metro, TypeScript, and bundler caches can cause issues
- Test in isolation: Ensure packages work independently
- Document dependencies: Make it clear which packages depend on React Native
- Use path aliases: Configure TypeScript paths for cleaner imports
Advanced: Turborepo Integration
turbo.json