react-native-video-player
What is react-native-video-player
The react-native-video-player
is a customizable video player for React Native apps, built on top of react-native-video
. It simplifies video playback with intuitive controls and seamless integration.
As TheWidlarzGroup, we revived this library after over two years of inactivity. We modernized it by replacing class-based components with functional ones, adding TypeScript support, fixing bugs, and ensuring compatibility with the latest react-native-video
versions.
How to Improve Performance and Manage Rerenders
While working on the react-native-video-player library, we identified a critical performance issue: every state update triggered unnecessary rerenders across multiple components. Although the app functioned correctly, its performance required significant optimization.
We took on the challenge of modernizing and optimizing the library - addressing unnecessary rerenders, enhancing overall performance, and reducing initial load times. Facing similar challenges in your app? Discover how our React Native expertise can help you achieve exceptional results.
We began by inspecting the app's behavior using the React Native Profiler. The results were overwhelming - many components were being updated repeatedly, even when it wasn’t necessary. This endless wave of rerenders made the app less efficient.
The profiler’s visual representation showed the problem clearly: nearly every component was being re-rendered with each state update, even when it didn't need to be.
As we analyzed the Profiler output, we noticed that each unnecessary rerender, even when no action was being performed, took around 3ms. These frequent updates involved many views that didn't actually need to be updated. In reality, for a scenario like this, only specific elements like the seek bar and the duration display should be refreshed.
While the React Native Profiler is a powerful tool, we needed something more visual to better understand the rerendering behavior. Enter React-Scan: a tool that provides real-time visualization of which components are rendering. This made the analysis process much easier.
With React-Scan, we could clearly see components "blinking" on the screen every time a state update occurred. This visual feedback confirmed that our app had a serious rerendering problem that needed addressing.
After identifying the problem areas, we created a clear roadmap for optimization:
React.memo
: By memoizing components, we ensured they would re-render only when their props changed, significantly reducing unnecessary updates.onProgress
with ref
: Moving the onProgress
function into a ref
allowed it to operate independently of the render cycle, reducing the frequency of component updates.After implementing the first set of changes, we revisited the app's behavior using React-Scan to visualize the improvements in real time. The results were clear: unnecessary rerenders were significantly reduced, and the app's performance was much more stable. Components updated only when required, resulting in a much cleaner and more efficient rendering process.
Here's a React-Scan recording showing the app's improved behavior after the initial optimizations:
At this stage, the focus was on general improvements, such as breaking down components and reducing redundant updates. While the progress was promising, we hadn't yet turned to detailed Profiler metrics for guidance, knowing that further refinements would still be necessary.
Later, we analyzed the Profiler again to quantify the improvements. Here's a snapshot of the Profiler after the initial round of changes:
Looks like a significant improvement! Now, it's clear that unnecessary views are no longer being updated, and a standard frame takes around 1-2ms instead of the previous 3ms. However, some peaks are still visible, indicating operations that take longer than expected. Additionally, the first frame remains a notable issue, as it takes considerably more time compared to subsequent updates.
The peaks in the Profiler mainly occurred during animations, like opening or hiding controls. These spikes are a natural result of complex rendering during animations and are hard to eliminate entirely. To keep the library lightweight, we chose not to add dependencies like react-native-reanimated
, which could improve performance but would also increase the library's size.
We implemented several optimizations where feasible:
1. Consolidating Animation Logic
2. Addressing Performance Peaks
The peaks visible in the Profiler indicated that certain components or functions were still being updated unnecessarily or were performing costly operations. By isolating these components, we identified specific optimizations:
forwardRef
in areas where it was not strictly necessary.The slow initial render was a standout issue. To address this, we:
These targeted optimizations addressed most performance spikes, but the initial render time still required further improvements. Below is the Profiler snapshot reflecting the state after addressing general performance issues but before fully optimizing the load time:
As a result of these improvements, a standard frame now completes in about 0.5–1.5ms, and animation frames are under 10ms, but the first frame still showed a significant delay that needed to be tackled in the next stage.
Instant playback matters. Whether it’s a TikTok-like app or any video platform, first rendering isn’t enough - videos often needs to play instantly. Struggling with delays? Let’s fix it and optimize your app for smooth video performance.
Addressing the slow initial render was a key limitation in our optimization efforts. To tackle this, we implemented several targeted changes:
These changes brought great improvements. The first render time dropped dramatically, and subsequent updates remained lightning-fast. However, it’s important to note that the Video
component itself is relatively heavy, which imposes some unavoidable limitations on initial rendering. Despite this, the results look very promising. The improvements ensure that the app performs smoothly while maintaining a clean and lightweight library design.
We successfully brought the initial render time down to a great result! Of course, the exact time will vary slightly with each test, as other factors can influence the results. However, where the render time previously hovered around 30ms, it’s now around 10ms. 😊
Optimizing react-native-video-player
highlighted how much performance can be improved in an app with careful analysis and iterative refinement. Key takeaways include:
React.memo
to limit unnecessary updates.After optimization, the app consistently rendered in under 16 ms, ensuring smooth performance at 60 FPS.
If you’re looking to optimize your app's performance, integrate efficient solutions, or need guidance in maintaining and modernizing open-source libraries, we’re here to help. Get in touch with us today to explore how we can support your goals. At TheWidlarzGroup, we specialize in delivering high-performance, scalable applications and ensuring the sustainability of open-source projects