Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(expo-config-plugin): create config plugin for react-native-performance #145

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion docs/docs/fundamentals/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Since this package contains code that needs to be natively linked, you'll have t
npx pod-install
```

## Usage
## Vanilla React-Native Setup

The Performance profiler library needs to be initialized in all 3 parts of your app: Android Native, iOS Native, and TS.

Expand Down Expand Up @@ -59,6 +59,34 @@ Similarly, add this snipped in your iOS `AppDelegate.m`. Again, ensure that the
}
```

## Expo Setup

To use the `@shopify/react-native-performance` library in your project you'll need to set up the `app.json` to contain the following contents under the `plugins` section

```json
"plugins": [
"@shopify/react-native-performance/app.plugin.js"
],
```

The above setup will allow you to use most of the other performance plugins as well. If you want to use the Flipper plugins you'll need to install `react-native-flipper` and `expo-build-properties` and set flipper to true for iOS. See the example below.

```json
"plugins": [
"@shopify/react-native-performance/app.plugin.js",
[
"expo-build-properties",
{
"ios": {
"flipper": true
}
}
]
],
```

Finally run `npx expo prebuild` and the project will be set up for you. Keep in mind that, if a third-party library uses `"useFrameworks": "static"` for iOS, integrating Flipper will not work since it is incompatible. See the [Expo Documentation](https://docs.expo.dev/guides/using-flipper/#limitations) on this subject

### TS Initialization

Mount the `<PerformanceProfiler/>` component somewhere high up in your App tree. For example:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "This monorepo contains the packages related to profiling performance of React Native apps.",
"private": true,
"scripts": {
"build": "tsc -b && cd packages/flipper-plugin-react-native-performance && yarn build",
"build": "tsc -b && cd packages/flipper-plugin-react-native-performance && yarn build && cd ../react-native-performance && yarn build plugin",
"version": "bin/version.mjs",
"release": "lerna version --conventional-commits",
"generate": "plop",
Expand Down
1 change: 1 addition & 0 deletions packages/react-native-performance/app.plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('./plugin/build');
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#import "ReactNativePerformance.h"
#import <ReactNativePerformance/ReactNativePerformance-Swift.h>
#import "ReactNativePerformance-Swift.h"

static NSTimeInterval startupTimestamp = -1.0;

Expand Down
2 changes: 2 additions & 0 deletions packages/react-native-performance/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@
"react-native": "*"
},
"devDependencies": {
"@expo/config-plugins": "6.0.1",
"@quilted/react-testing": "^0.5.11",
"@testing-library/react-hooks": "^8.0.0",
"@testing-library/react-native": "^9.0.0",
"expo-module-scripts": "3.0.7",
"jest-extended": "^2.0.0",
"react-test-renderer": "17.0.2"
},
Expand Down
101 changes: 101 additions & 0 deletions packages/react-native-performance/plugin/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import {
ConfigPlugin,
withAppDelegate,
withMainApplication,
withPlugins,
withProjectBuildGradle,
} from '@expo/config-plugins';
import {mergeContents} from '@expo/config-plugins/build/utils/generateCode';
import {addImports} from '@expo/config-plugins/build/android/codeMod';

const MATCH_DID_FINISH_LAUNCHING_IOS =
/-\s*\(BOOL\)\s*application:\s*\(UIApplication\s*\*\s*\)\s*\w+\s+didFinishLaunchingWithOptions:/g;

const MATCH_ON_CREATE = /super\.onCreate\(\);/;
const MATCH_DEPENDANCIES = /dependencies {/;

const withRequiredIOSSetup: ConfigPlugin = expoConfig => {
const importStatement = '#import <ReactNativePerformance/ReactNativePerformance.h>';
const newLine = ' [ReactNativePerformance onAppStarted];\n';

return withAppDelegate(expoConfig, iosConfig => {
if (!['objc', 'objcpp'].includes(iosConfig.modResults.language)) {
throw new Error(
"@shopify/react-native-performance config plugin does not support AppDelegate' that aren't Objective-C(++) yet.",
);
}

iosConfig.modResults.contents = mergeContents({
tag: 'react-native-performance-import-ios',
src: iosConfig.modResults.contents,
newSrc: importStatement,
offset: 0,
comment: '//',
anchor: '',
}).contents;

iosConfig.modResults.contents = mergeContents({
tag: 'react-native-performance-didFinishLaunchingWithOptions-ios',
src: iosConfig.modResults.contents,
newSrc: newLine,
offset: 2,
comment: '//',
anchor: MATCH_DID_FINISH_LAUNCHING_IOS,
}).contents;

return iosConfig;
});
};

const withRequiredAndroidMainApplicationSetup: ConfigPlugin = expoConfig => {
const importStatement = 'com.shopify.reactnativeperformance.ReactNativePerformance';
const newLine = ' ReactNativePerformance.onAppStarted();\n';
return withMainApplication(expoConfig, async androidConfig => {
if (androidConfig.modResults.language !== 'java') {
throw new Error('@shopify/react-native-performance config plugin does not support kotlin MainActivity yet.');
}

const srcWithNewImport = addImports(
androidConfig.modResults.contents,
[importStatement],
androidConfig.modResults.language === 'java',
);

androidConfig.modResults.contents = mergeContents({
tag: 'react-native-performance-onCreate-android',
src: srcWithNewImport,
newSrc: newLine,
anchor: MATCH_ON_CREATE,
offset: 0,
comment: '//',
}).contents;

return androidConfig;
});
};

const withRequiredAndroidBuildGradleSetup: ConfigPlugin = expoConfig => {
const newLine = " classpath('org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0+')";
return withProjectBuildGradle(expoConfig, async androidConfig => {
androidConfig.modResults.contents = mergeContents({
tag: 'react-native-performance-appBuildGradle-android',
src: androidConfig.modResults.contents,
newSrc: newLine,
anchor: MATCH_DEPENDANCIES,
offset: 1,
comment: '//',
}).contents;

return androidConfig;
});
};

const withReactNativePerformanceSetup: ConfigPlugin = config => {
return withPlugins(config, [
withRequiredIOSSetup,
withRequiredAndroidBuildGradleSetup,
withRequiredAndroidMainApplicationSetup,
]);
};

export default withReactNativePerformanceSetup;
9 changes: 9 additions & 0 deletions packages/react-native-performance/plugin/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "expo-module-scripts/tsconfig.plugin",
"compilerOptions": {
"outDir": "build",
"rootDir": "src"
},
"include": ["./src"],
"exclude": ["**/__mocks__/*", "**/__tests__/*"]
}
Loading