-
Notifications
You must be signed in to change notification settings - Fork 140
Running Flagship Apps
Contents
Flagship and Flagship apps use Yarn for dependency management. Simply run yarn
in the project root to make sure that your project's dependencies are up-to-date.
Whenever you pull down or write new code, you'll need to run TSC in order to compile the TypeScript code into vanilla JS before it can be run on device with React Native.
From your project root, run ./node_modules/.bin/tsc
or simply tsc
if you have the package installed globally.
Note: Most Flagship apps and the Flagship Template project define TSC as part of the prepare
hook in package.json
, meaning that TSC will run whenever you run yarn
, making this extra step unnecessary.
Whenever you pull down a project for the first time, add native dependencies to your project, or update your environment files you'll need to run Flagship init.
Note that you do not need to re-run init unless you change native dependencies or environment files!
The init script does the following:
- Copies the
ios
andandroid
folders from@brandingbrand/flagship
into your project. These contain the native projects for iOS and Android. - Edits the native projects to customize values per your configuration for items such as app name and bundle identifier.
- Runs
react-native link
to install native dependencies. - Runs custom scripts defined in the Flagship package to set up native dependencies that don't link automatically.
- Adds native dependencies using Cocoapods (iOS) and Gradle (Android).
- Registers your environment files and generates
env.js
for the current selected environment.
You can manually run init as follows: ./node_modules/.bin/flagship init
However, we recommend adding a convenience script to your project's package.json that wraps the script with a clean step that removes the ios and android directories ahead of time. (This already exists in projects created with the Flagship Project Template.)
"scripts": {
"init": "flagship clean && flagship init native"
}
This would be run as follows: yarn run init
To start your app in an iOS simulator, you can simply run ./node-modules/.bin/react-native run-ios
. However, please note that this doesn't account for TypeScript so you'll need to run tsc
whenever you make a change before it'll appear on your simulator.
To accommodate for this, Branding Brand apps and the Flagship Template app define a convenience script in package.json
that starts up a TypeScript file watcher, the React Native packager, and the app in one go.
It normally looks like this in package.json
:
"compile-ios": "react-native run-ios --simulator \"iPhone X\" --no-packager",
"ios": "run-p start tsc:watch compile-ios"
And you run it like this:
yarn run ios
This will launch the app in a simulator and automatically run TSC whenever your code changes.
- Connect your device to your computer with a USB cable
- Open Xcode
- Use the "Open" menu to open /ios/.xcworkspace
- Select your device from the devices dropdown (top left next to the app name)
- Click the Run (▶) button to run the app on your selected device
- Note that you will need to run
tsc
after making changes in your code to be reflected in your app
Unlike iOS, React Native cannot start an Android emulator. As such, you'll need to manually start an emulator before continuing.
- Open Android Studio
- Select Tools > AVD Manager
- Click "Create Virtual Device" and follow the wizard to create a new emulator, or click the start (▶) button to launch an existing emulator
To start your app in an Android emulator, you can simply run ./node-modules/.bin/react-native run-android
. However, please note that this doesn't account for TypeScript so you'll need to run tsc
whenever you make a change before it'll appear on your simulator.
To accommodate for this, Branding Brand apps and the Flagship Template app define a convenience script in package.json
that starts up a TypeScript file watcher, the React Native packager, and the app in one go.
It normally looks like this in package.json
:
"compile-android": "react-native run-android --no-packager",
"android": "run-p start tsc:watch compile-android"
And you run it like this:
yarn run android
This will launch the app in the emulator and automatically run TSC whenever your code changes.
- Connect an Android device to your computer via USB
- Open the Settings app
- Navigate to "About phone"
- Tap on the "Build number" item 10x in a row to enable developer mode
- Go back to the main Settings menu and select "Developer options"
- Verify that the "USB debugging" checkbox is enabled
- You may need to change your phone's USB mode from charging only to data transfer mode. Refer to your phone's documentation for more information.
- From your computer, run adb devices which will list all physical and emulator devices and their debugging status
- If the device isn't displayed, either the phone isn't in developer mode, USB debugging mode is disabled, or the USB mode is set to charging only
- If the device is listed as "unauthorized", USB debugging is disabled or you haven't given the current computer permission to access your device. Try tapping "Revoke USB debugging authorizations" and then turn USB debugging off then on again and you should get a prompt to allow debugging
- If the device is listed as "device" debugging should be ready to go.
Once your device is set up for development, the process is the same as running on an emulator: run ./node_modules/.bin/react-native run-android
or yarn run android
and the app will run on your connected Android device. Note that if you use run-android
you'll need to manually run tsc
whenever you make a change to your code.
When running for web, you'll need to make sure that your application has been initialized for web so that the /web folder has been generated. You can do this by running flagship init web
.
Running in development mode will compile your application and serve it immediately, updating as you make changes. You can do this by running yarn start
inside of the /web folder. Generally this is done with a script in your package.json that looks like:
"compile-web": "(test -d 'web' || flagship init web) && cd ./web/ && yarn start"
If you need to proxy api requests, you can run a seperate server which will handle that with yarn server-dev
inside of the /web folder.
You can also build the application for production mode, which will compile everything into the /web-compiled folder. This can be served directly by running start-prod
inside the /web folder, or you can run it with proxy support with server-prod
.
Once you've built for production, you can also compile your application to be rendered server-side by running build-ssr
inside the /web folder. This will build a function that you can pass an Express application into which will add middleware routes for each of your screens, which will wind up as /web/ssr-build/attachSSR.js. For it to build this, you'll need to create a ssr.ts file inside your /src folder. This will look the same as your index.web.ts file, but replace these lines:
const app = new FSApp(webConfig);
export default app;
with:
export default function(app: any, options?: SSROptions): void {
attachSSR(app, webConfig, options);
}
To share data that you've loaded server-side with your client-side application, you'll also want to add this to your index.web.ts file before calling new FSApp
to initialize redux with that data:
// @ts-ignore May be set by SSR
if (window.initialState) {
webConfig.initialState = {
...webConfig.initialState,
// @ts-ignore
...window.initialState
};
}
Once you've built for both production and server-side rendering, you can either use it with your own Express app or run server-ssr
inside the /web folder to run your application with proxy and server-side-rendering support.
By default, your screens will be served at /_s/{screenname}, but can be overridden by setting a static path
string on the screen.
If you want to load some data specifically for the screen, add a static loadInitialData
function to it of the form:
(data: FSAppTypes.SSRData, req: Express.Request) => Promise<FSAppTypes.SSRData>
where data is the initialState from the application configuration and a variables object, and returns a Promise including an update of that. req is the Express request object, in case there is any information you need to pull out of it.
If you have a screen where you want it to skip being rendered server-side and you want your Express application to handle it instead, set a static instantNext
value to true
. If you need some sort of logic based on the responses from loadInitialData or anything else, you can specify shouldNext
, which takes this form:
(data: FSAppTypes.SSRData, req: Express.Request) => Promise
and should return true if you want to abort rendering and call next
instead.
You can also specify a cache
number for how long a screen's responses should be cached.
For data that should be loaded more globally, you'll want to specify cachedData and/or uncachedData functions in your application configuration. These take the form:
(initialData: FSAppTypes.SSRData, req?: Express.Request): Promise<FSAppTypes.SSRData>
and are run both server-side and client-side, where req is undefined client-side. The exception is that uncachedData is not run server-side for cached pages, so should contain any requests for user-specific data, like account or cart data.
Getting Started
- Flagship Technical Introduction
- Setting up Your Development Environment
- Getting Started with Flagship
- Creating a Flagship App
How To
- Running Flagship Apps
- Managing Environments
- Creating App Icons
- Creating Launch Screens
- Signing Your Apps
- Using React Native Permissions v2
- Using SSL Certificate Pinning
- Initializing Multiple Xcode Targets
Major Releases