A simple react-native cli wrapper to make some of the trivial native tasks simpler and easier.
- Use configuration instead of making changes to native code.
- Make it easier to release apps for android as well as iOS. Ready to deploy on Play Store and App Store.
- Make react-native project yarn workspaces friendly.
- Provide a Splash screen for android as well.
WARNING: This utility still needs a lot more testing with different use cases. It is however directly compatilbe with react-native cli, so you can always revert back to using react-native cli any time. Uses react-native version 0.56 while creating new project, but the utility should work with prior react-native verions as well. Read below for instructions
$ npm install -g react-native-foundation
or
$ yarn global add react-native-foundation
$ foundation create <ProjectName>
This command works similar to react-native init
except that
the project will not include the native sources, but a
foundation.config.js
file, which could be used to configure
the most trivial native configurations.
$ foundation run-android
$ foundation run-ios
This command will build the native code and publish the app on the connected device (simulator) for development purpose. These command delegate their task to their respective react-native commands, but before doing that, they make changes to the native code, to reflect back the configuration.
$ foundation start
This command will start the packager, making sure that you
are able to run them with or without the native codes. It just
needs an index.js
to serve. Will work even without a valid
node package.json
.
$ foundation create-native
You will almost always need to change the native code specially
when it comes to shipping. This command will create native
source android
and ios
on your workspace (yarn).
Note that if you have multiple react-native project on your
yarn workspace there can only be one native source for all your react native project. This is most likely the usecase when you are working through a workspace. There isn't a
workaround for this, and you will have to opt to multiple
yarn workspaces if you need separate native codes.
Also checkout the nativeRepo
configuration that allows you
to maintain your own native repo, just make sure that you
inherit your native repo from that provided by the foundation.
The native source for android
and ios
makes a few subtle
changes to incorporate the configurations automatically.
- Android
app/build.gradle
- Read app specific confgiration from a json file dynamically. - Android
app/src/main/res/strings.xml
- The display name is also provided and henceapp_name
has been removed. - Android
app/src/main/res/drawable/splash_background.xml
SplashTheme
has been added as a background for launch screen. - Android
app/src/main/res/values/styles.xml
. SplashTheme using the Splash Background has been defined. - Android
app/src/main/AndroidManifest.xml
SplashActivity
has been added with an Intent to Launch.MainActivity
usesSplashTheme
as background. Just make sure your app renders with a background color to avoid showing the Splash Theme. - Android
..../SplashActivity.java
Activity file for showing the Launch screen. - iOS Uses CocoaPods to manage dependencies.
- iOS
Foundation/AppDelegate.m
is modified to display launch screen for an extended period, to avoid showing white screen when the javascript side loads. (Extracted from react-native pro-tip) - iOS Uses PlistBuddy to change
Foundation/Info.plist
dynamically to updatename
,version
,bundleId
andbuild
when building ios app.
The following changes need to be made to your native code
in the react-native project, for the foundation commands
to work.
For iOS
- Include foundation.config.js in the project root.
- Add ios specific configuration in the config file.
ios: { scheme: '<RNProject>' }
. The scheme name is typically what you used to create the React Native project. This should be the main folder insideios
and should have the same scheme available for building. foundation run-ios
should now run the ios app on the simulator,foundation release-ios
should generate ios app ready for publishing andfoundation upload-ios
should upload the app to the app store via iTunes connect.
For Android
- Include foundation.config.js in the project root.
- Edit
android/app/build.gradle
to update app information- Add the following line on top
def manifestJson = new groovy.json.JsonSlurper().parseText(file('../../build/manifest.json').text);
- Use
manifestJson.bundleId
fordefaultConfig.applicationId
. - Use
manifestJson.build
fordefaultConfig.versionCode
- Use
manifestJson.version
fordefaultConfig.versionName
- Include the following command somewhere inside
defaultConfig
resValue "string", "app_name", manifestJson.appName
- Add the following line on top
- Edit
android/app/src/main/res/values/strings.xml
and remove the line that defines app name<string name="app_name">....</string>
- Remove any signing configuration that has been added
to
android/app/build.gradle
. Provide the keystore file via thefoundation.config.js
. Otherwiserelease-android
command might not work. foundation run-android
should now build the android app as perfoundation.config.js
andfoundation release-android
should generate apk ready for publishing. Note that therun-android
command will only create the apk, but will not be able to start the Activity (TODO).- The splash screen won't be available with these changes. It's however pretty easy, if you check how it works. Will document it later.
appName
: The name of the app as displayed on your mobilebundleId
: A unique id that identifies your app on play store or app store.version
: A short text version name displayed on app store or play store.build
: A version number or build number used by play store and app store to track the version of your app.launcher
: A folder location that provides app launcher icons of all sizes. The folder should contain files for all phone resolutions which should be named as:- For android:
ic_launcher-mdpi.png
ic_launcher-hdpi.png
ic_launcher-xhpi.ong
ic_launcher-xxhpi.ong
ic_launcher-xxxhpi.ong
- For ios:
ios-20@1x.png
ios-20@2x.png
ios-20@3x.png
ios-29@1x.png
ios-29@2x.png
ios-29@3x.png
ios-40@1x.png
ios-40@2x.png
ios-40@3x.png
ios-60@2x.png
ios-76@1x.png
ios-76@2x.png
ios-83.5@2x.png
ios-1024@1x.png
- For android:
splash
: A folder location that provides splash icons for all screen sizes.- For android:
ic_splash-mdpi.png
ic_splash-hdpi.png
ic_splash-xhpi.png
ic_splash-xxhdpi.png
ic_splash-xxxhdpi.png
- For ios:
ios-splash@1x.png
ios-splash@2x.png
ios-splash@3x.png
- For android:
nativeRepo
: You can build your custom native repo and use it instead of the stock foundation repo. Just make sure your native repo supports foundation.android
: Android specific configuration. This can include all the above configurations exceptnativeRepo
additionally provide:keyStore
: Path to android key store file required for signing your app for releasing to Google Play Store.
ios
: iOS specific configuration. This can override all the above configuratios exceptnativeRepo
additionaly provide:teamId
: The 10 character Apple team id available on your apple developer account.developerId
: The user id to login to your Apple developer account for publishing.
You could also use the Sketch App Template for the launcher
and splash
icons.
foundation.config.js
module.exports = {
appName: 'Name of the app',
bundleId: 'com.sharingapples.foundation', // Identity of your app on play store or app store
build: 10, // An incremental build number (android version code or ios Build
version: '1.3.0', // A version text
android: {
keyStore: '~/secrets/my-apps-key.keystore'
},
ios: {
teamId: '1234567890', // You 10 character team id
developerId: 'someone@somewhere.com', // Your developer account id,
},
};
You can easily release your app to Google Play Store and Apple App Store with simple commands.
Android:
$ foundation release-android
With proper configuration, this command will generate an
apk ready to upload for Google Play Store. Make sure you
have properly configured your foundation.config.js
with
sigining keys.
iOS:
$ foundation release-ios
This command will generate ipa
files that are ready to
be deployed for app store. Make sure to include your
teamId in configuration.
$ foundation upload-ios
This command will use your apple developer account and submit the app for review on app store. Make sure to include your developerId (email address) in configuration.
- If you are working with yarn workspaces. Make sure:
- The native libraries dependencies are also there on
your workspace
package.json
, even if they have been added to your apps'package.json
. - There is an
index.js
on your workspace root, which simply imports your targetted apps index.js.import './packages/your-app'
. This is needed since the ios and android javascript bundling works relative to where yourreact-native
package is installed. - If there is a
.babelrc
in your workspace root, make sure it hasreact-native
as a preset. Also includebabel-preset-react-native
as dev dependency.
- The native libraries dependencies are also there on
your workspace
- Add release configurations in
foundation.config.js
.
android.keyStore
: Path to keystore required for app signing
ios.teamId
: The iOS team id for publishing your app
ios.developerId
: The apple developer id (email) - Environment variables for setting password
ANDROID_KEY_STORE_PASS
: password required for reading the key store file.
APPLER_DEVELOPER_PASS
: password to apple developer account to publish app via itunes connect.
If the passwords are not set, they would have to be provided during the release process
$ foundation info
Display information as per your configuration.
$ foundation info-ios
Display information considering ios platform.
$ foundation info-android
Display information considering android platform.
The react-native apps use Foundation
as a default module name. So yes, in development mode you could use the same
native app to load different apps being served by the metro
bundler, and as long as there is no difference in react-native
version or native modules, your app should load just fine.
It's actually one of the way to improve app development. Build
one app with all your native dependencies. Deploy it on all
your test devices. And run foundation start
anywhere.