From 2823307c62a8ded1978f9ffe390160a18af0f50d Mon Sep 17 00:00:00 2001 From: Pascal Hartig Date: Mon, 6 Apr 2020 08:24:55 -0700 Subject: [PATCH] Add RN Android/iOS docs Summary: I trimmed the previous versions of this down a lot to only focus on what RN developers need to know without duplicating what we have in the non-RN docs. Reviewed By: mweststrate Differential Revision: D20816115 fbshipit-source-id: 9d88a6fb0d49e823194cce647e64b86d61d6229a --- docs/getting-started/react-native-android.md | 117 ++++++++++++ docs/getting-started/react-native-ios.md | 177 +++++++++++++++++++ docs/getting-started/react-native.md | 30 ++-- scripts/bump/bump.hs | 2 + website/i18n/en.json | 8 + website/sidebars.json | 4 +- 6 files changed, 321 insertions(+), 17 deletions(-) create mode 100644 docs/getting-started/react-native-android.md create mode 100644 docs/getting-started/react-native-ios.md diff --git a/docs/getting-started/react-native-android.md b/docs/getting-started/react-native-android.md new file mode 100644 index 000000000..f81099f39 --- /dev/null +++ b/docs/getting-started/react-native-android.md @@ -0,0 +1,117 @@ +--- +id: react-native-android +title: Manually set up your React Native Android App +sidebar_label: React Native for Android +--- + +These instructions are aimed at people manually adding Flipper to a React Native 0.62+ app. +This should only be necessary if you have an existing app that cannot be upgraded with the +[React Native Upgrade tool](https://reactnative.dev/docs/upgrading). + +## Dependencies + +Flipper is distributed via JCenter. Add the dependencies to your `build.gradle` file. +You should also explicitly depend on [`soloader`](https://github.com/facebook/soloader) +instead of relying on transitive dependency resolution which is getting deprecated +with Gradle 5. + +```groovy +repositories { + jcenter() +} + +dependencies { + debugImplementation('com.facebook.flipper:flipper:0.35.0') { + exclude group:'com.facebook.fbjni' + } + + debugImplementation('com.facebook.flipper:flipper-network-plugin:0.35.0') { + exclude group:'com.facebook.flipper' + } +} +``` + +These exclusions are currently necessary to avoid some clashes with FBJNI +shared libraries. + +## Application Setup + +For maximum flexibility, we recommend you move the Flipper initialization to a separate +class that lives in a `debug/` folder, so that Flipper code never gets referenced in a +release build. + +```java +import android.content.Context; +import com.facebook.flipper.android.AndroidFlipperClient; +import com.facebook.flipper.android.utils.FlipperUtils; +import com.facebook.flipper.core.FlipperClient; +import com.facebook.flipper.plugins.inspector.DescriptorMapping; +import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; +import com.facebook.react.ReactInstanceManager; +import okhttp3.OkHttpClient; + +public class ReactNativeFlipper { + public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { + if (FlipperUtils.shouldEnableFlipper(context)) { + final FlipperClient client = AndroidFlipperClient.getInstance(context); + + client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); + } + } +} +``` + +Note that this only enables the Layout Inspector plugin. Check out [the React Native template](https://github.com/facebook/react-native/blob/6f627f684bb6506a677c9632b2710e4a541690a9/template/android/app/src/debug/java/com/helloworld/ReactNativeFlipper.java) for more plugins. + +In your `Application` implementation, we then call the static method using +reflection. This gives us a lot of flexibility, but can be quite noisy. +Alternatively, recreate an empty `ReactNativeFlipper` class in a `release/` folder, +so you can call into the method directly. + +```java +public class MainApplication extends Application implements ReactApplication { + // ... + + @Override + public void onCreate() { + super.onCreate(); + SoLoader.init(this, /* native exopackage */ false); + initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); + } + + /** + * Loads Flipper in React Native templates. Call this in the onCreate method with something like + * initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); + * + * @param context + * @param reactInstanceManager + */ + private static void initializeFlipper( + Context context, ReactInstanceManager reactInstanceManager) { + if (BuildConfig.DEBUG) { + try { + /* + We use reflection here to pick up the class that initializes + Flipper, since Flipper library is not available in release mode + */ + Class aClass = Class.forName("com.example.ReactNativeFlipper"); + aClass + .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) + .invoke(null, context, reactInstanceManager); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + } +} +``` + +## Further Steps + +To create your own plugins and integrate with Flipper using JavaScript, check out our [writing plugins for React Native](tutorial/react-native) tutorial! \ No newline at end of file diff --git a/docs/getting-started/react-native-ios.md b/docs/getting-started/react-native-ios.md new file mode 100644 index 000000000..d0e23877f --- /dev/null +++ b/docs/getting-started/react-native-ios.md @@ -0,0 +1,177 @@ +--- +id: react-native-ios +title: Manually set up your React Native iOS App +sidebar_label: React Native for iOS +--- + +These instructions are aimed at people manually adding Flipper to a React Native 0.62+ app. +This should only be necessary if you have an existing app that cannot be upgraded with the +[React Native Upgrade tool](https://reactnative.dev/docs/upgrading). + +## Dependencies + +Add this code to your `ios/Podfile`: + +```ruby +platform :ios, '9.0' + +def flipper_pods() + flipperkit_version = '0.35.0' + pod 'FlipperKit', '~>' + flipperkit_version, :configuration => 'Debug' + pod 'FlipperKit/FlipperKitLayoutPlugin', '~>' + flipperkit_version, :configuration => 'Debug' + pod 'FlipperKit/SKIOSNetworkPlugin', '~>' + flipperkit_version, :configuration => 'Debug' + pod 'FlipperKit/FlipperKitUserDefaultsPlugin', '~>' + flipperkit_version, :configuration => 'Debug' + pod 'FlipperKit/FlipperKitReactPlugin', '~>' + flipperkit_version, :configuration => 'Debug' +end + +# Post Install processing for Flipper +def flipper_post_install(installer) + installer.pods_project.targets.each do |target| + if target.name == 'YogaKit' + target.build_configurations.each do |config| + config.build_settings['SWIFT_VERSION'] = '4.1' + end + end + end + file_name = Dir.glob("*.xcodeproj")[0] + app_project = Xcodeproj::Project.open(file_name) + app_project.native_targets.each do |target| + target.build_configurations.each do |config| + cflags = config.build_settings['OTHER_CFLAGS'] || '$(inherited) ' + unless cflags.include? '-DFB_SONARKIT_ENABLED=1' + puts 'Adding -DFB_SONARKIT_ENABLED=1 in OTHER_CFLAGS...' + cflags << '-DFB_SONARKIT_ENABLED=1' + end + config.build_settings['OTHER_CFLAGS'] = cflags + end + app_project.save + end + installer.pods_project.save +end + +target 'your-app-name' do + ... + + + # Replace the existing yoga import with the following (adding modular_headers): + pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga', :modular_headers => true + + ... + use_native_modules! + + # For enabling Flipper. + # Note that if you use_framework!, flipper will not work. + # Disable these lines if you are doing use_framework! + flipper_pods() + post_install do |installer| + flipper_post_install(installer) + end +end +``` + +Install the dependencies by running `cd ios && pod install`. You can now +import and initialize Flipper in your AppDelegate. + +## Initialization + +The code below enables the following integrations: + +- Layout Inspector +- Network +- Shared Preferences +- Crash Reporter + + + + + +```objective-c +... +#if DEBUG +#ifdef FB_SONARKIT_ENABLED +#import +#import +#import +#import +#import +#import +#import +#endif +#endif + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + [self initializeFlipper:application]; + ... +} + +- (void) initializeFlipper:(UIApplication *)application { + #if DEBUG + #ifdef FB_SONARKIT_ENABLED + FlipperClient *client = [FlipperClient sharedClient]; + SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults]; + [client addPlugin: [[FlipperKitLayoutPlugin alloc] initWithRootNode: application withDescriptorMapper: layoutDescriptorMapper]]; + [client addPlugin: [[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]]; + [client addPlugin: [FlipperKitReactPlugin new]]; + [client addPlugin: [[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]]; + [client start]; + #endif + #endif +} + +@end +``` + + + +```swift +... +#if DEBUG +#if FB_SONARKIT_ENABLED +import FlipperKit +#endif +#endif + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + func application( + _ application: UIApplication, + didFinishLaunchingWithOptions + launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + initializeFlipper(with: application) + ... + } + + private func initializeFlipper(with application: UIApplication) { + #if DEBUG + #if FB_SONARKIT_ENABLED + let client = FlipperClient.shared() + let layoutDescriptorMapper = SKDescriptorMapper(defaults: ()) + FlipperKitLayoutComponentKitSupport.setUpWith(layoutDescriptorMapper) + client?.add(FlipperKitLayoutPlugin(rootNode: application, with: layoutDescriptorMapper!)) + client?.add(FKUserDefaultsPlugin(suiteName: nil)) + client?.add(FlipperKitReactPlugin()) + client?.add(FlipperKitNetworkPlugin(networkAdapter: SKIOSNetworkAdapter())) + client?.add(FlipperReactPerformancePlugin.sharedInstance()) + client?.start() + #endif + #endif + } +} +``` + + + +Lastly, open the Flipper desktop app, and run `yarn ios` in your terminal. + +## Troubleshooting + +If you can't build your app after adding Flipper, you may need to configure the Swift compiler. To do so, adding an empty Swift file in your project is the easiest way. + +## Further Steps + +To create your own plugins and integrate with Flipper using JavaScript, check out our [writing plugins for React Native](tutorial/react-native) tutorial! \ No newline at end of file diff --git a/docs/getting-started/react-native.md b/docs/getting-started/react-native.md index 990496c20..6b93b7779 100644 --- a/docs/getting-started/react-native.md +++ b/docs/getting-started/react-native.md @@ -4,20 +4,10 @@ title: Set up your React Native App sidebar_label: React Native --- -
+Starting with React Native 0.62, after generating your project with `react-native init`, the Flipper integration is ready out of the box for debug builds: -This tutorial is for React Native applications using version **0.62.0**, please refer to the following if you are using a different version: - -* [Flipper on RN < 0.61.5 tutorial](https://github.com/facebook/flipper/blob/da25241f7fbb06dffd913958559044d758c54fb8/docs/getting-started.md#setup-your-react-native-app) -* [Flipper on RN 0.61.5 - 0.62 tutorial](https://github.com/facebook/flipper/blob/4297b3061f14ceca4d184aa3eebd0731b5bf20f5/docs/getting-started.md#setup-your-react-native-app) - -
- - -After generating your project with `npx react-native init`, the Flipper integration is setup out-of-the-box for debug builds: - -* For Android, start the Flipper Desktop application, and start your project using `yarn android`. Your application should appear in Flipper. -* For iOS, run `pod install` once in the `ios` directory of your project. After that, run `yarn ios` and start Flipper. Your application should show up in Flipper. +* For Android, start the Flipper Desktop application, and start your project using `yarn android`. Your application will appear in Flipper. +* For iOS, run `pod install` once in the `ios` directory of your project. After that, run `yarn ios` and start Flipper. Your application will show up in Flipper. By default, the following plugins will be available: @@ -30,8 +20,16 @@ By default, the following plugins will be available: * React DevTools * Metro Logs -Additional plugins might be installed through NPM, please follow the instructions as provided by the plugin authors. +Additional plugins can be installed through the plugin manager. -To create your own plugins and integrate with Flipper using JavaScript, check out our [writing plugins for React Native](tutorial/react-native) tutorial! +To create your own plugins and integrate with Flipper using JavaScript, check out our [writing plugins for React Native](/docs/tutorial/react-native) tutorial! -If you ever need to update the Flipper SDKs used in your project, the versions can be bumped in the `ios/Podfile` and `android/gradle.properties` files of your project. \ No newline at end of file +To update the Flipper SDK in your project, you bump the version in the `ios/Podfile` and `android/gradle.properties` files of your project. + +## Manual Setup + +If you are not using a default React Native template or cannot use the upgrade tool, +you can find instructions for how to integate Flipper into your projects in these guides: + +- [React Native for Android](/docs/getting-started/react-native-android) +- [React Native for iOS](/docs/getting-started/react-native-ios) \ No newline at end of file diff --git a/scripts/bump/bump.hs b/scripts/bump/bump.hs index ea1aca0ed..62bfcf901 100755 --- a/scripts/bump/bump.hs +++ b/scripts/bump/bump.hs @@ -30,6 +30,8 @@ releaseReplacements = [("gradle.properties", "VERSION_NAME=" *> anyVersion) ,("docs/getting-started/android-native.md", spaces >> "debugImplementation 'com.facebook.flipper:flipper:" *> releaseVersion <* "'") ,("docs/getting-started/android-native.md", spaces >> "releaseImplementation 'com.facebook.flipper:flipper-noop:" *> releaseVersion <* "'") + ,("docs/getting-started/react-native-android.md", spaces >> "debugImplementation 'com.facebook.flipper:flipper:" *> releaseVersion <* "'") + ,("docs/getting-started/react-native-android.md", spaces >> "debugImplementation 'com.facebook.flipper:flipper-network-plugin:" *> releaseVersion <* "'") ,("docs/setup/leak-canary-plugin.md", spaces >> "debugImplementation 'com.facebook.flipper:flipper-leakcanary-plugin:" *> releaseVersion <* "'") ,("docs/setup/layout-plugin.md", spaces >> "debugImplementation 'com.facebook.flipper:flipper-litho-plugin:" *> releaseVersion <* "'") ,("docs/setup/network-plugin.md", spaces >> "debugImplementation 'com.facebook.flipper:flipper-network-plugin:" *> releaseVersion <* "'") diff --git a/website/i18n/en.json b/website/i18n/en.json index e4c6f36fd..0ff6f1510 100644 --- a/website/i18n/en.json +++ b/website/i18n/en.json @@ -113,6 +113,14 @@ "title": "Set up your iOS app", "sidebar_label": "iOS" }, + "getting-started/react-native-android": { + "title": "Manually set up your React Native Android App", + "sidebar_label": "React Native for Android" + }, + "getting-started/react-native-ios": { + "title": "Manually set up your React Native iOS App", + "sidebar_label": "React Native for iOS" + }, "getting-started/react-native": { "title": "Set up your React Native App", "sidebar_label": "React Native" diff --git a/website/sidebars.json b/website/sidebars.json index 451c13f74..d186fd136 100644 --- a/website/sidebars.json +++ b/website/sidebars.json @@ -21,7 +21,9 @@ "getting-started/index", "getting-started/android-native", "getting-started/ios-native", - "getting-started/react-native" + "getting-started/react-native", + "getting-started/react-native-android", + "getting-started/react-native-ios" ], "Plugin Setup": [ "setup/layout-plugin",