In this session, I will discuss our experiences in overcoming performance limitations while developing React components for web apps on low-end embedded devices such as Smart TVs. I will share actual application cases from the development of millions of webOS Smart TVs and show how we improved user input response and app launch time. The ideas and techniques shared will be beneficial to developers facing similar challenges.
Overcoming Performance Limitations in React Components for Low-end Devices
AI Generated Video Summary
This Talk discusses overcoming performance limitations in React components for low-end devices, focusing on app launch time and scrolling performance. The speaker shares techniques for improving app launch and scrolling performance, such as pre-rendering, generating HTML at build time, and using the Virtual List component. The Virtual List component recycles dominoes and uses Translate3D function for improved performance. Delegating scrolling to the browser in NativeMode and supporting scrolling via remote control keys are also mentioned. Overall, the Talk highlights the importance of optimizing performance for low-end devices and provides practical solutions for achieving better performance in React components.
1. Introduction to Overcoming Performance Limitations
I will talk about overcoming performance limitations in React components for low-end devices. Low-end devices such as smart TVs and set-top boxes often have limited hardware performance. In this talk, I will focus on app launch time and scrolling performance.
Hi, everyone. I'm so excited to talk about overcoming performance limitations in React components for low-end devices. My name is Seungho from LG Electronics and I'm leading the Enact framework. Enact is a React-based app framework designed for TV UI components, remote control navigation, accessibility, and internationalization. It's used on millions of webOS TVs, including the apps you see on LG OLED TVs.
In this talk, I will share our experiences in overcoming performance limitations when we create a React component for those apps. Low-end devices such as smart TVs and set-top boxes often have limited hardware performance. This makes it challenging to develop high-performance web apps on these devices. There are lots of performance metrics, but in this talk, I will focus only on app launch time and scrolling performance.
2. Improving App Launch and Scrolling Performance
App launch time is crucial for delivering a native quality experience on smart devices. We improved performance through pre-rendering, generating HTML at build time, and using VSnapshot for system apps. Scrolling performance is critical for media-type apps on TV devices. We improved it by creating the Virtual List component.
Let's talk about app launch time first. App launch time is one of the most important performance metrics on smart devices to deliver a native quality experience to users. When developing the In-App Framework, the biggest challenge was to provide fast and smooth performance so that the user can't tell if it is a native web or web app. So how did we improve from left to right? To obvious, we applied pre-rendering. You've probably seen this picture before. It's from the web.dev for explaining the server-side rendering.
Since our goal is to develop pre-installed apps for the device, we choose a structure that is closer to CSR with pre-rendering. This is a very simplified version of our pre-rendering flow. This is a typical React App build. We transpile the JSX and ESCX code and package it. At this build time, we use the node server to call the renderToString function. This generates the HTML for the first screen and we package the app with this HTML. When we run the app, we call the hydrateRoot function instead of the createRoot function. To support over 200 locales, we generate pre-rendered HTML for each locale at build time. Duplicate content is saved as multi.html. A localeMap.json file maps the locale to the HTML file and an ebin4.json file, which is the M-metadata, specifies the HTML file as the main entry point. Pro-tip, we use VSnapshot for system apps. This is a highly specific operation and definitely isn't ideal for everybody. However, it is useful in certain scenarios, and this will help simplify the process. We made the snapshot plugin, and it assumes usage of React. This plugin requires you to obtain a MKSnapshot binary. It is usually tied to the specific version of Chromium that you are targeting. Pay careful attention to have matching versions. Launch time depends on the complexity and size of the app. But generally, the VSNapshot made app launch time faster by more than 30%.
Let's talk about scrolling performance. On TV devices, media-type apps like the Media Player need to scroll through many great items. Therefore, ensuring smooth scrolling is critical to provide a native app quality experience to users. So, how did we improve from left to right? To handle very long list items, we created the Virtual List component. Virtualized techniques are now in common, and there are many great virtualized list components out there.
3. Virtualization and Native Scrolling
The Virtual List component recycles dominoes to improve performance. The Translate mode moves the container div with the Translate3D function. We achieved 60 fps on all devices by delegating scrolling to the browser in NativeMode. TBFs support scrolling via remote control keys. We have improved app launch time and scrolling performance using pre-rendering, VSNapture, and virtualization with native scrolling. Thank you for watching!
The idea of virtualization is that instead of creating all new dominoes, we recycle them into visible dominoes. This screen is a layer of Virtual List component. There is a long container div that is the full height of the entire list. Each item element is above it. We create each of these item dominoes in slightly larger numbers than the visible viewport.
As the user scrolls down the list, we scroll the container div. When the first item leaves the viewport, we move it to the bottom of the items. In this way, we recycle the dom. This is a simple flow of Virtual List in Translate mode. We call it Translate mode because we are moving the container div with the Translate3D function. When the user rotates the wheel, we listen to the OnWheel event. From this event information, we calculate the distance to be moved. In the animator, we move the container by calling Translate3D function. As the container moves, we virtualize items. And this behavior is done inside the Request animation frame.
However, this wasn't enough to achieve 60 FPS on low-end devices. So we tried to delegate scrolling to the browser. We call it NativeMode because the browser is moving the container there. This eliminates the distance calculation and the entire behavior of moving the container within the Request animation frame. Instead, we only need to look at the OnScroll event and handle the item virtualization within that event. Finally, we were able to achieve 60 fps on all devices.
TBFs need to support scrolling via remote control up and down keys. To move the container element via the arrow keys, we call the scrollTo() function. Use the smooth option for zoomed scrolling. For continuous key input, we need to calculate the proper coordinate and select the smooth or instant options. From the previous native mode flow, we need to add onKeyDownEvent handler. In this handler, we calculate the coordinate and call scrollTo() function to move the container element.
We are now on the final page. Let's summarize. To improve app launch time, we have used pre-rendering and VSNapture. To improve scrolling performance, we have used virtualization with native scrolling. By applying these techniques, we have been able to create high-performance React components that deliver native quality experience on low-end devices. Thank you for watching everybody. I hope you really enjoy my presentation and found it useful.