Repository navigation
feat: add perf metrics - #494
Merged
Merged
Conversation
… TTFD hook (#493) * fix(bgp): track RN bundle dirs as merge task inputs Static source directories added through the variant API are not task inputs, so a rebuilt JS bundle left mergeAssets/packageResources UP-TO-DATE and the AAR shipped the previous bundle. Register the generated assets/res dirs (including the expo-updates resources) as inputs of those tasks. * fix(Expo): respect safe-area insets on the postMessage tab Pad the postMessage tab with the safe-area insets (and the bottom tab inset) so its content is not drawn under the status bar or tab bar when the Expo surface is hosted full screen. ExpoApp56's Jest setup mocks react-native-safe-area-context, since the tests render the tab without a SafeAreaProvider. * feat(AndroidApp): host React Native in a full-screen ReactNativeActivity Move the embedded RN fragment out of MainActivity's scroll view into a dedicated ReactNativeActivity pushed from an "Open React Native" button, mirroring RNAppScreen on iOS. Each launch creates a new fragment, so every presentation reports its own TTID/TTFD. The activity now owns the BrownfieldNavigation delegate. Detox suites open the RN screen through the new button instead of scrolling the native shell, and window-focus recovery no longer brings MainActivity to the front while another app activity is resumed. * test(AppleApp): open RN via accessibility id, keep postMessage toast on top Give the "Open React Native" button an accessibility identifier so the Detox suites tap it directly instead of matching by text, and move the postMessage toast above the NavigationView so it stays visible while the pushed RN screen is in front. * feat(examples): mark TTFD from every example app via a shared hook Add a useMarkFullyDisplayed hook to RNApp, ExpoApp56 and ExpoApp57 and call it from each root (and the Expo Router root). It marks the presentation fully displayed after DEMO_FULL_DISPLAY_DELAY_MS, which stands in for the data a real screen would load first. ExpoApp56 never called markFullyDisplayed even though its Android flavor waits for full display, so it reported no display metrics at all. * test(AndroidApp): tap RN-to-native navigation buttons with sync off The vanilla settings/referrals tests tapped an RN <Button> with Detox synchronization on. The press queues ripple view commands, and onPress pushes a native activity straight away; once ReactNativeActivity pauses, Fabric never mounts those commands, so FabricUIManagerIdlingResources stays busy ("View command mount items pending: 1") and the tap times out intermittently. Tap with sync off and wait for the native screen through UIAutomator, which the tests already did for the assertion.
…feat/perf-metrics
Contributor
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The Gradle compatibility fixture, iOS lockfile, and Expo presentation timing need correction before approval.
6 open findings
Use output-bearing task types in the AGP compatibility fixture · New Clear bundle observer state after failed loads · New Preserve caller props for unmeasured views · New Start TTID measurement only after the real root is inserted · New Correct Objective-C reference for Android callback contract · New Correct Swift callback name and JSBundleTimings contract · New
🧠 Review effort: Lite
Add a Performance Metrics guide covering startup timings, TTID, TTFD, JS FPS and UI FPS. Document markFullyDisplayed in the JavaScript API reference and remove PERFORMANCE.md.
The plugin wires createBundle<Variant>JsAndAssets jsBundleDir/resourcesDir outputs as generated sources and fails fast without them, so plain tasks.register stubs broke the AGP compatibility matrix.
A failed reload left didLoadBundle and latestTimings from the previous load, so a new onBundleLoaded registration got stale timings right away.
The merge duplicated the boost, BrownfieldNavigation and React-bridging entries, which made pod install crash.
Views, view controllers and fragments created without the metrics APIs now keep their initial props as is and create no display session, on both iOS and Android.
With Expo Updates, view() returns a placeholder and inserts the root later. The appearance probe sat in the placeholder, so initial display could complete before the root existed, or when its creation failed. The probe now goes into the real root, and the view controller reports appearance only after that.
AppleApp preloads the JS bundle at launch, and the RN view now sits behind the Open React Native button. DetoxSync keeps the app busy on React Native (bundle load) until RN content appears, so re-enabling sync on the native shell made the app never go idle and every iOS test timed out. Sync is turned back on by openReactNative once the RN screen is visible.
Detox's element tap injects a synthesized touch at the accessibility activation point, which SwiftUI's NavigationLink ignores: the tap was reported as successful, but the RN screen was never pushed. Tap the center of the Open React Native button through XCUITest (device.tap) instead, which delivers a real touch.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
This PR introduces performance metrics which can be used to track for observability OR custom usage. The supported metrics are:
JS Bundle:
Screen Based:
Test plan