This application is built with the following principles.
- Offline first - All data that is brought into the app should be stored immediately in Ion which puts the data into persistent storage (eg. localStorage on browser platforms).
- UI Binds to Ion - UI components bind to Ion so that any change to the Ion data is automatically reflected in the component by calling setState() with the changed data.
- Actions manage Ion Data - When the UI needs to request or write data from the server, this is done through Actions exclusively.
- Actions should never return data, see the first point. Example: if the action is
fetchReports()
, it does not return the reports,fetchReports()
returns nothing. The action makes an XHR, then puts the data into Ion (usingIon.set()
orIon.merge()
). Any UI that is subscribed to that piece of data in Ion is automatically updated.
- Actions should never return data, see the first point. Example: if the action is
- Cross Platform 99.9999%
- A feature isn't done until it works on all platforms. Accordingly, don't even bother writing a platform-specific code block because you're just going to need to undo it.
- If the reason you can't write cross platform code is because there is a bug in ReactNative that is preventing it from working, the correct action is to fix RN and submit a PR upstream -- not to hack around RN bugs with platform-specific code paths.
- If there is a feature that simply doesn't exist on all platforms and thus doesn't exist in RN, rather than doing if (platform=iOS) { }, instead write a "shim" library that is implemented with NOOPs on the other platforms. For example, rather than injecting platform-specific multi-tab code (which can only work on browsers, because it's the only platform with multiple tabs), write a TabManager class that just is NOOP for non-browser platforms. This encapsulates the platform-specific code into a platform library, rather than sprinkling through the business logic.
- Put all platform specific code in a dedicated branch, like /platform, and reject any PR that attempts to put platform-specific code anywhere else. This maintains a strict separation between business logic and platform code.
- Install
node
&npm
:brew install node
- Install
watchman
:brew install watchman
- Install dependencies:
npm install
- Run
cp .env.example .env
and edit.env
to have your local config options
- To run a Development Server:
npm run web
- To build a production build:
npm run build
- Changes applied to Javascript will be applied automatically
- The web app automatically deploys via a GitHub Action in
.github/workflows/main.yml
- To install the iOS dependencies, run:
cd ios/ && pod install
- To run a on a Development Simulator:
npm run ios
- If the app is booting on a simulator for the first time, run the following two commands:
xcrun simctl keychain booted add-root-cert ~/Expensidev/config/ssl/rootCA.crt #Adds root cert and trusts it xcrun simctl keychain booted add-cert ~/Expensidev/config/ssl/expensify.com.dev.pem #Adds .dev cert and trusts it
- Changes applied to Javascript will be applied automatically, any changes to native code will require a recompile
- Running via
ngrok
is required to communicate with the API- Start ngrok (
Expensidev/script/ngrok.sh
), replaceexpensify.com.dev
value in.env
with your ngrok value
- Start ngrok (
- To run a on a Development Emulator:
npm run android
- Changes applied to Javascript will be applied automatically, any changes to native code will require a recompile
- To install the required tools to deploy, run
bundle install
from the root of this project - To deploy the iOS app run:
npm run deploy-ios
- The Android app automatically deploys via a GitHub action to: https://chat.expensify.com/app-release.apk
- To build an APK to share run (e.g. via Slack):
Build > Generate Signed Bundle / APK...
from Android Studio
- To run the Development app, run:
npm run desktop
- To build a production build, run:
npm run desktop-build
- The desktop app automatically deploys via a GitHub Action in
.github/workflows/desktop.yml
- To run the Jest Unit Tests:
npm run test
- If you are having issues with Getting Started, please reference React Native's Documentation
- If you are running into issues communicating with
expensify.com.dev
(CORS, SSL, etc.), running viangrok
is recommended, see step 3 in Getting Started
- If running on the iOS simulator
⌘D
, or⌘M
on Android emulator will 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