⚠️ Warning: Nx has not been fully battle-tested in Expo environments. Users have reported ongoing issues with bugs, errors, and path resolving in application-centric monorepos. Consider alternatives if you're working with Expo, like Yarn v4. Learn more.
The utopia is to code once and have a native app and a native website.
We can be close to that heaven. If we go deep into Typescript & React ecosystem, there are some libraries to make a scalable cross-platform application:
- Components, app and web in one repository to share dependencies, devOps (like CI/CD processes, publishing...), all thanks to Nx
- App: React Native with Expo
- Web: React with NextJS
- App and web navigation: Expo Router and Solito
- Cross theme for web (CSS) and mobile with Tamagui
- Allow setting up Android compileSdkVersion and others nrwl/nx#26572
- Nx add more dependencies to the Expo app nrwl/nx#26571
- Nx + Expo with Yarn causes problems as pointed at nrwl/nx#22631, nrwl/nx#26257, nrwl/nx#21101. Solution: use NPM in Nx, else seperate the monorepo from the Expo app like here https://github.com/guillempuche/nx-monorepo-with-expo-standalone-app
- Nx + Expo with NPM is able to run Expo Go app, but not a local build as pointed at nrwl/nx#26285. Solution: seperate the monorepo from the Expo app like here https://github.com/guillempuche/nx-monorepo-with-expo-standalone-app (I didn't finish it)
- Next configuration file uses ESM and throws
ERR_UNSUPPORTED_DIR_IMPORT
error in Tamagui. Solution: #4
- [WIP] Make sure Nx always build the Android and iOS app.
- Create Storybook.
- Replecate Expo app in Next and Vite app.
- Test it with NodeJS v18. You can use NVM (Node Version Manager) or fnm to manage multiple Node versions.
- Install
yarn
and enable the latest version with running this commandyarn set version berry
. You can usenpm
easily, just delete:- The
packageManager
field inpackage.json
- The
yarn.lock
file
- The
- Replace the monorepo's name for yours. Get tge name found in
package.json
fieldname
(e.g.nx-expo-next-tamagui
), find all of them around the code and replace them for your desired name.
Don't consider this character
@
, we don't replace or migrate it.
- Install all the dependencies with
yarn install
. - For mobile
- Set up Android and iOS environment. Guide at React Native docs. My current Android setup is for Android API 34.
- Run Android emulator. Check your local emulators with
emulator -list-avds
, then run it (e.g.emulator -avd Resizable_API_34
). - Run the Expo app found as
expo
(it's the name of the package found inapps/expo
). You could change the name with Nx console (read the suggestions section below). Run the commandyarn exec nx run expo:start
and open the app according to the terminal commands. You can check what are the commands run by Nx onapps/expo/project.json
file --> sectiontargets
-->start
.
- For web:
- Run the NextJS web with
yarn exec nx run next:serve
- Run the Vite React web with
yarn exec nx run web-react:serve
- Run the NextJS web with
- When adding new libraries to the monorepo, consider referencing the names in
@tamagui/babel-plugin
inapps/expo/babel.config.js
(and in other apps you create). And if the libraries use Tamagui, then create thetamagui.config.js
file. - For Expo app
- When updating
expo
,expo-router
,metro
,@nx/expo
or related packages that needs configuration (e.g.metro.config.js
,babel.config.js
,app.json
,package.json
,project.json
,tamagui.config.js
...), consider symlinks compatibility with Metro. Keep an eye on Metro's changelog here, even if Expo says is better to user other Metro versions, test other versions. - If you do some dependency changes and the Expo app doesn't work, check which installed packages need to be updated with:
npx expo-doctor
([docs](npx expo install --check
)) andnpx expo install --check
(docs). - If you have errors running the app, you can enable Nx debug mode in
apps/expo/metro.config.js
, setdebug
totrue
.
- When updating
- To create new libraries or apps, use the Nx extension for VSCode or JetBrains (download it here). The other option is using the CLI, however, you can make more errors. After creating the library/app, compared with boilerplate libraries and apps to clean unused settings (test, dependencies... or whatever you don't want) for Nx, React, Metro, Expo, NextJS, Tamagui...
- I couldn't run the Expo app using pnPm (the alternative to NPM and Yarn package managers). I think the problem is with symlinks, even when changing the config like npmrc-->node-linker doesn't work.
- My Android (e.g. SDKMAN to manage Java versions) and iOS environment configuration for macOS with Zsh, my
~/.zshrc
file:
#################################
############# NVM (Node Version Manager)
# More info https://github.com/nvm-sh/nvm/blob/master/README.md
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
# Loads nvm
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
# Loads nvm bash_completion
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
#################################
############# ANDROID STUDIO
export ANDROID_SDK_ROOT=$HOME/Library/Android/sdk
# sdkmanager https://developer.android.com/studio/command-line/sdkmanager
export PATH=$PATH:$ANDROID_SDK_ROOT/cmdline-tools/latest/bin
# adb (Android Debug Bridge) https://developer.android.com/studio/command-line/adb
export PATH=$PATH:$ANDROID_SDK_ROOT/platform-tools
# emulator https://developer.android.com/studio/command-line/adb
# $ emulator -list-avds
# $ emulator -avd <device_name> -port 5555
export PATH=$PATH:$ANDROID_SDK_ROOT/emulator
export PATH=$PATH:/Users/your_profile_name/.sdkman/candidates/java/current
# For React Native, support older tooling
export ANDROID_HOME=$HOME/Library/Android/sdk
# Android Studio would need to create this symlink in Macos in the app's internal files
# ln -sfn ./jbr ./jre
#################################
############# COCOA PODs
# More info https://guides.cocoapods.org/using/getting-started.html#sudo-less-installation
export GEM_HOME=$HOME/.gem
# export PATH=$GEM_HOME/ruby/2.6.0/bin:$PATH
export PATH=$GEM_HOME/bin:$PATH
#################################
############# MAVEN
export PATH=$PATH:/Users/your_profile_name/programacio/programes/apache-maven-3.8.6/bin
#################################
############# SDKMAN
# Enable Gradle
export JAVA_HOME="$HOME/.sdkman/candidates/java/current"
# THIS MUST BE AT THE END OF THE FILE FOR SDKMAN TO WORK
export SDKMAN_DIR="$HOME/.sdkman"
[[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh"
- Nx packages (AKA, the plugins) at nx.dev/plugin-registry where you can find all you need to create, edit and run the monorepo.
- Expo settings and plugins at docs.expo.dev.
- Tamagui theme at tamagui.dev and advanced monorepo template Takeout.
- Expo Router v2 at expo-router/CHANGELOG.md and docs.