Blog
Reviving and Optimizing react-native-video-player: From Outdated to Efficient and Modern

Reviving and Optimizing react-native-video-player: From Outdated to Efficient and Modern

Discover how we modernized and optimized the react-native-video-player library, tackling unnecessary rerenders, improving performance, and reducing initial load times. Learn about our approach to maintaining open-source projects and delivering lightweight solutions for React Native apps
Tags
React Native
Optimalization
React Native Video
Mobile development
Open Source

Optimizing 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.

1. Starting with the Profiler

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.

2. Taking It to the Next Level with React-Scan

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.

3. The Action Plan

After identifying the problem areas, we created a clear roadmap for optimization:

  1. Breaking Down Components: The app's monolithic structure caused every state update to affect the entire component tree. Splitting it into smaller, more focused components allowed us to isolate updates.
  2. Using React.memo: By memoizing components, we ensured they would re-render only when their props changed, significantly reducing unnecessary updates.
  3. Refactoring 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.

4. The Initial Results

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.

5. Focusing on the Details

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

  • We moved all animation-related logic into a single component.

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:

  • Refactored complex logic into lightweight utility functions to minimize runtime overhead.
  • Reduced the usage of forwardRef in areas where it was not strictly necessary.
3. Tackling the First Frame

The slow initial render was a standout issue. To address this, we:

  • Split the video player and thumbnail display into separate components, ensuring that each handled only its specific tasks during the first render.
  • Simplified initialization logic, reducing the number of operations performed during the first frame.

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.

6. Tackling the Slow Initial Render

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:

  1. Separated Video and Thumbnail Components: Splitting the video player and thumbnail into independent components, along with specific logic for each, reduced complexity during the initial render.
  2. Streamlined Initialization: We refactored initialization logic to reduce the workload during the first render.

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. 😊

7. Conclusion

Optimizing react-native-video-player highlighted how much performance can be improved in an app with careful analysis and iterative refinement. Key takeaways include:

  • Breaking down components and using React.memo to limit unnecessary updates.
  • Minimized performance peaks, reducing their impact on rendering performance.
  • Minimizing the initial render time, creating a smoother user experience from the start.

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

Thank you! Your submission has been received! 📨
Oops! Something went wrong while submitting the form.
React Native
Optimalization
React Native Video
Mobile development
Open Source
No items found.
Do you need help with developing react solutions?

Leave your contact info and we’ll be in touch with you shortly

Leave contact info
Become one of our 10+ ambassadors and earn real $$$.