|
1 | 1 | # Expo Router Migration |
2 | 2 |
|
3 | | -## Status: Blocked - Awaiting React Native Upgrade |
| 3 | +## Status: Evaluated & Intentionally Deferred |
4 | 4 |
|
5 | | -## Summary |
| 5 | +## Decision (December 2025) |
6 | 6 |
|
7 | | -Attempted migration to Expo Router v3 for file-based routing but encountered compatibility issues with the current bare React Native 0.74.5 setup. |
| 7 | +After upgrading to React Native 0.81.5 and Expo SDK 54 (which removed the original blockers), we re-evaluated Expo Router and decided **not to migrate**. |
8 | 8 |
|
9 | | -## Current Setup (Working) |
| 9 | +### Why We're Skipping It |
10 | 10 |
|
11 | | -- **React Native**: 0.74.5 |
12 | | -- **Expo SDK**: 51 |
| 11 | +| Factor | Assessment | |
| 12 | +|--------|------------| |
| 13 | +| **App complexity** | Only 3 screens (Home, Settings, SyncDebug) | |
| 14 | +| **Navigation needs** | Simple stack - no nested routes, tabs, or drawers | |
| 15 | +| **Deep linking** | Not needed for a sync settings UI | |
| 16 | +| **Web support** | Android-only app | |
| 17 | +| **Current solution** | React Navigation works perfectly fine | |
| 18 | + |
| 19 | +### Cost vs Benefit |
| 20 | + |
| 21 | +**Costs of migrating:** |
| 22 | +- Additional dependencies (`expo-router`, `expo-linking`, `expo-constants`, `@expo/metro-runtime`) |
| 23 | +- More complex Metro/Babel configuration |
| 24 | +- Migration effort (~2-4 hours) |
| 25 | +- Previous attempt had `require.context` issues in bare RN |
| 26 | + |
| 27 | +**Benefits:** |
| 28 | +- File-based routing (marginal - we only have 3 screens) |
| 29 | +- Automatic deep links (not needed) |
| 30 | +- Slightly less boilerplate (trade ~50 lines in `index.tsx` for `_layout.tsx`) |
| 31 | + |
| 32 | +**Verdict:** Over-engineering for a 3-screen settings UI. |
| 33 | + |
| 34 | +## Current Setup (Working Well) |
| 35 | + |
| 36 | +- **React Native**: 0.81.5 |
| 37 | +- **Expo SDK**: 54 |
13 | 38 | - **Navigation**: React Navigation (`@react-navigation/native-stack`) |
14 | | -- **UI Components**: Gluestack UI v1 |
15 | | -- **Styling**: NativeWind v2 (Tailwind for RN) |
| 39 | +- **UI Components**: Gluestack UI v2 |
| 40 | +- **Styling**: NativeWind v4 |
16 | 41 | - **Entry Point**: `index.tsx` with explicit screen imports |
| 42 | +- **Screens**: `app/index.tsx`, `app/settings.tsx`, `app/sync-debug.tsx` |
| 43 | + |
| 44 | +## When to Reconsider |
| 45 | + |
| 46 | +Expo Router would make sense if the app grows to include: |
| 47 | +- 10+ screens with complex navigation flows |
| 48 | +- Nested navigators (tabs within stacks, drawers, etc.) |
| 49 | +- Web support requirements |
| 50 | +- Deep linking for sharing specific screens |
| 51 | + |
| 52 | +## Historical Context |
| 53 | + |
| 54 | +Originally blocked on RN 0.74.5 / Expo 51 due to: |
| 55 | +- `require.context` failures in bare RN |
| 56 | +- Dependency version conflicts with expo-module-gradle-plugin |
| 57 | +- NativeWind v4 / react-native-worklets incompatibilities |
17 | 58 |
|
18 | | -## Target Versions for Original Goals |
19 | | - |
20 | | -| Package | Current | Target | Why | |
21 | | -|---------|---------|--------|-----| |
22 | | -| **React Native** | 0.74.5 | **0.76.x** | New Architecture required for worklets | |
23 | | -| **Expo SDK** | 51 | **52** | Expo Router v4 + updated gradle plugins | |
24 | | -| **Expo Router** | ❌ removed | **~4.x** | Better bare RN support in v4 | |
25 | | -| **NativeWind** | 2.x | **4.x** | Requires RN 0.76+ for worklets | |
26 | | -| **react-native-svg** | 15.2.0 (broken) | **15.x** | Compatible with RN 0.76+ | |
27 | | - |
28 | | -### Upgrade Helper |
29 | | - |
30 | | -Use this link to see all required changes: |
31 | | -https://react-native-community.github.io/upgrade-helper/?from=0.74.5&to=0.76.0 |
32 | | - |
33 | | -## What We Tried |
34 | | - |
35 | | -### Expo Router v3 |
36 | | -- File-based routing in `app/` directory |
37 | | -- `require.context` for auto-discovery of routes |
38 | | -- `ExpoRoot` component as entry point |
39 | | - |
40 | | -### NativeWind v4 |
41 | | -- Direct Tailwind CSS integration |
42 | | -- `withNativeWind` Metro wrapper |
43 | | - |
44 | | -## Issues Encountered |
45 | | - |
46 | | -### 1. `require.context` Failure |
47 | | -Expo Router uses `require.context('./app')` to auto-discover route files. This relies on Metro's experimental features that didn't work in this bare RN setup - `ExpoRoot` couldn't find any routes, resulting in blank screens. |
48 | | - |
49 | | -### 2. Dependency Version Conflicts |
50 | | -- `expo-router@~3.5.x` → `expo-linking@~6.3.x` → expected newer gradle plugin infrastructure |
51 | | -- `expo-module-gradle-plugin` version mismatches between Expo SDK 51 packages |
52 | | -- `react-native-svg@15.x` incompatible with RN 0.74.5 (downgraded to 13.x) |
53 | | - |
54 | | -### 3. NativeWind v4 Incompatibilities |
55 | | -- Required `tailwindcss@3.x` (v4 not supported) |
56 | | -- `react-native-worklets` incompatible with RN 0.74.5 |
57 | | -- `lightningcss` platform-specific binaries failed in Windows/WSL environment |
58 | | - |
59 | | -### 4. Windows/WSL Environment |
60 | | -- Separate `node_modules` on Windows and Linux due to file sync |
61 | | -- Native binary dependencies (like `lightningcss`) need platform-specific builds |
62 | | - |
63 | | -## Migration Checklist |
64 | | - |
65 | | -### Prerequisites |
66 | | -- [ ] Upgrade to React Native 0.76.x |
67 | | -- [ ] Upgrade to Expo SDK 52 |
68 | | -- [ ] Verify New Architecture is enabled |
69 | | -- [ ] Clean rebuild on Windows (`.\gradlew clean`) |
70 | | - |
71 | | -### Migration Steps |
72 | | -1. [ ] Add `expo-router@~4.x` and `expo-linking` |
73 | | -2. [ ] Update `package.json` main to `"expo-router/entry"` |
74 | | -3. [ ] Update `app.json` with expo-router plugin |
75 | | -4. [ ] Recreate `app/_layout.tsx` with providers |
76 | | -5. [ ] Update screen files to use `useRouter()` instead of `useNavigation()` |
77 | | -6. [ ] Add NativeWind v4 + tailwindcss v3 |
78 | | -7. [ ] Update `metro.config.js` with `withNativeWind` |
79 | | -8. [ ] Test on Windows/WSL environment |
80 | | -9. [ ] Remove React Navigation packages |
81 | | - |
82 | | -## Files to Reuse |
83 | | - |
84 | | -These files were created and can be adapted: |
85 | | - |
86 | | -| File | Status | Notes | |
87 | | -|------|--------|-------| |
88 | | -| `app/index.tsx` | ✅ Working | Update imports for expo-router | |
89 | | -| `app/settings.tsx` | ✅ Working | Update imports for expo-router | |
90 | | -| `app/sync-debug.tsx` | ✅ Working | No navigation changes needed | |
91 | | -| `lib/components/ui/` | ✅ Working | Keep as-is | |
92 | | -| `lib/theme/colors.ts` | ✅ Working | Keep as-is | |
93 | | -| `lib/navigation/types.ts` | ⚠️ Remove | Not needed with expo-router | |
94 | | -| `app/_layout.tsx` | ❌ Deleted | Recreate with expo-router imports | |
95 | | - |
96 | | -## References |
97 | | - |
98 | | -- [Expo Router Docs](https://docs.expo.dev/router/introduction/) |
99 | | -- [NativeWind v4 Docs](https://www.nativewind.dev/) |
100 | | -- [React Native Upgrade Helper](https://react-native-community.github.io/upgrade-helper/?from=0.74.5&to=0.76.0) |
101 | | -- [Expo SDK 52 Release Notes](https://expo.dev/changelog) |
102 | | -- [React Native 0.76 Release](https://reactnative.dev/blog) |
| 59 | +These blockers were resolved by upgrading to RN 0.81.5 / Expo 54, but the migration was deemed unnecessary for the app's scope. |
0 commit comments