This project uses Rock to manage native builds. Rather than compiling native code locally when running commands like npm run ios, Rock first attempts to download remote builds (artifacts prebuilt on CI) from S3. If a matching remote build isn’t available, it automatically falls back to building locally.
By storing complete native build artifacts remotely, Rock reduces the need for local compilation and simplifies setup through automated downloads.
Note: Any changes to files involved in generating a fingerprint (e.g., package.json) will trigger a local build.
The following steps describe how to configure the project to fully utilize Rock.
- To install project dependencies run:
npm install - To start metro server run:
npm run startNote: For now this is a required step — metro needs to be called manually in a separate terminal. - To run application on a Development Simulator:
- For standalone
npm run ios-standalone - For hybrid app
npm run ios
- For standalone
After completing these steps, you should be able to start both mobile platform apps using the remote build.
If you haven't done any intentional edits outside of src/ (like adding new dependencies) but your app is still running into a full build, remember that it's way easier to debug and address a remote cache miss rather than any compilation error.
-
Try re-installing dependencies:
npm run i-standalonefor the standalone appnpm installfor the hybrid app
-
Try running:
- For standalone
npm run ios-standalone - For hybrid app
npm run ios
- For standalone
-
If you’re still encountering errors, you can try running:
git clean -fdx ios/when running standalone appgit clean -fdx ./Mobile-Expensifywhen running hybrid app
-
Then try running again:
- For standalone
npm run ios-standalone - For hybrid app
npm run ios
- For standalone
-
If the issue persists, verify that both workflows in the GitHub repository have completed successfully:
- iOS builds If the workflows are still running, open them and verify they match your fingerprint. Once complete, Rock should download the remote build. If not, check whether the last main commit hash merged into your branch has the same fingerprint as yours.
If the fingerprints do not match, run:
npx rock fingerprint -p ios --verboseCompare the results with the GitHub Actions output to see which files have different fingerprints.
-
In the event of workflow failures, it is recommended to have the option to manually build the application. The following steps will cover the manual build process.
For an M1 Mac, read this Stack Overflow post for installing cocoapods.
-
Install Xcode and iOS Platform
- Install Xcode tools and make sure to install the optional "iOS Platform" package as well. This installation may take awhile.
- After installation, check in System Settings that there's no update for Xcode. Otherwise, you may encounter issues later that don't explain that you solve them by updating Xcode.
-
Install Ruby and Bundler
- Install project gems, including cocoapods, using bundler to ensure everyone uses the same versions. In the project root, run:
bundle install - If you get the error
Could not find 'bundler', install the bundler gem first:gem install bundlerand try again. - If you are using MacOS and get the error
Gem::FilePermissionErrorwhen trying to install the bundler gem, you're likely using system Ruby, which requires administrator permission to modify. To get around this, install another version of Ruby with a version manager like rbenv.
- Install project gems, including cocoapods, using bundler to ensure everyone uses the same versions. In the project root, run:
-
Configure MapBox
- Before installing iOS dependencies, you need to obtain a token from Mapbox to download their SDKs. Please run
npm run configure-mapboxand follow the instructions. - For help with MapBox token, you can see this Slack thread
- Before installing iOS dependencies, you need to obtain a token from Mapbox to download their SDKs. Please run
-
Install iOS Dependencies
- To install the iOS dependencies, run:
npm install && npm run pod-install
- To install the iOS dependencies, run:
- To run on a Development Simulator:
npm run ios - Changes applied to Javascript will be applied automatically, any changes to native code will require a recompile
If you want to run the app on an actual physical iOS device, please follow the instructions here.
If you are an Expensify employee and want to point the emulator to your local VM, follow this
To receive mobile push notifications in the development build while hitting the Staging or Production API, you need to use the production airship config.
Set inProduction to true in Mobile-Expensify/iOS/AirshipConfig/Debug/AirshipConfig.plist
Replace the development key and secret with the production values.
To test the web app in iOS simulator browsers, you need to install the development certificate. The development server uses HTTPS protocol, so the iOS simulator needs the same certificate installed.
You must first configure HTTPS certificates by following the instructions in the Web Setup Guide.
- Run
npm run setupNewDotWebForEmulators ios - Select the emulator you want to run if prompted. (If single emulator is available, then it will open automatically)
- Let the script execute till the message
🎉 Done!.
If you want to set up both iOS and Android simulators at once:
- Run
npm run setupNewDotWebForEmulators allornpm run setupNewDotWebForEmulators - Check if the iOS flow runs first and then Android flow runs.
- Let the script execute till the message
🎉 Done!.
- If running on the iOS simulator pressing
⌘Dwill open the debugging menu. - This will allow you to attach a debugger in your IDE, React Developer Tools, or your browser.
- For more information on how to attach a debugger, see React Native Debugging Documentation
Alternatively, you can also set up debugger using Flipper. After installation, press ⌘D and select "Open Debugger". This will open Flipper window. To view data stored by Onyx, go to Plugin Manager and install async-storage plugin.
Within Xcode head to the build phase - Bundle React Native code and images.
export SOURCEMAP_FILE="$(pwd)/../main.jsbundle.map" // <-- here;
export NODE_BINARY=node
../node_modules/react-native/scripts/react-native-xcode.sh- Install the necessary packages and CocoaPods dependencies:
npm i && npm run pod-install - Run your iOS app in production mode
- Navigate to the feature you wish to profile.
- Initiate the profiling session by tapping with four fingers to open the menu and selecting
Use Profiling. - Close the menu and interact with the app.
- After completing your interactions, tap with four fingers again and select to stop profiling.
- You will be presented with a
Shareoption to export the trace, which includes a trace file (Profile<app version>.cpuprofile) and build info (AppInfo<app version>.json).
- You have two files:
AppInfo<app version>.jsonandProfile<app version>.cpuprofile - Place the
Profile<app version>.cpuprofilefile at the root of your project. - If you have already generated a source map from the steps above for this branch, you can skip to the next step. Otherwise, obtain the app version from
AppInfo<app version>.jsonswitch to that branch and generate the source map as described.
IMPORTANT: You should generate the source map from the same branch as the trace was recorded.
- Upon completion, the generated source map can be found at:
main.jsbundle.map - Use the following command to symbolicate the trace:
npm run symbolicate-release:ios - A new file named
Profile_trace_for_<app version>-converted.jsonwill appear in your project's root folder. - Open this file in your tool of choice:
- SpeedScope (https://www.speedscope.app)
- Perfetto UI (https://ui.perfetto.dev/)
- Google Chrome's Tracing UI (chrome://tracing)
- If you are having issues with Getting Started, please reference React Native's Documentation
- For additional iOS-specific troubleshooting, see the HybridApp documentation
Note: Expensify engineers that will be testing with the API in your local dev environment please refer to these additional instructions.