A real-world case study on optimizing React SPA performance.
Website performance isn't just about loading time. Providing a fast and responsive user experience is critical, especially for the productivity desktop applications that people use every day. The engineering team of Recruitment technologies went through a refactoring project to improve one of its web applications, AirSHIFT, for better user input performance. This is how they did it.
Slow response, lower productivity
AirSHIFT is a desktop web application that helps shop owners, such as restaurants and cafes, manage the shift work of their staff members. Built with React, the single-page app provides rich client functionality including multiple shift schedule grid tables organized by day, week, month, and more.

As the Recruit Technologies engineering team added new features to the AirSHIFT app, they started getting more feedback on slow performance. AirSHIFT Engineering Manager Yosuke Furukawa said:
In a user research study, we were surprised when one of the store owners said that he would leave his seat to make coffee after clicking a button, just to kill time waiting for the shift table to load.
After conducting the research, the engineering team realized that many of its users were trying to load massive shift tables onto low-spec computers, such as a 1 GHz Celeron M laptop from 10 years ago.
Endless spinner on low-end devices.
La aplicación AirSHIFT estaba bloqueando el hilo principal con scriptsConcepto de Scripts¿Qué son los Scripts?Los Scripts son fragmentos de código que se usan para dar forma a herramientas tanto en Internet como en el sector de la informática en general. Son una parte crucial del software, puesto que se trata exactamente del código que conforma a una aplicación en su totalidad o a una de sus funciones, como además el que puedes hallar explorando cómo está hecha una web.Desde plus costosos, pero el equipo de ingeniería no se dio cuenta de lo costosos que eran los scripts porque se estaban desarrollando y probando en computadoras de especificaciones ricas con conexiones Wi-Fi rápidas.

When loading the shift table, about 80% of the loading time was consumed by executing scripts.
After profiling its performance in Chrome DevTools with CPU and network throttling enabled, it became clear that performance needed to be optimized. AirSHIFT formed a working group to address this issue. Here are 5 things they focused on to make their app more responsive to user input.
1. Virtualize large tables
Displaying the shift table required several costly steps: building the virtual DOM and rendering it on the screen in proportion to the number of staff members and time slots. For example, if a restaurant has 50 working members and you want to check their monthly shift schedule, it would be a table of 50 (members) multiplied by 30 (days), resulting in 1,500 cell components to render. This is a very expensive operation, especially for low-spec devices. In reality, things were worse. From the investigation, they discovered that there were stores managing 200 staff members, requiring around 6,000 cell components in a single monthly table.
To reduce the cost of this operation, AirSHIFT virtualized the shift table. The application now only mounts the components inside the viewport and unmounts the components outside the screen.

Before: rendering all the cells of the shift table.

After: just render the cells within the viewport.
In this case, AirSHIFT used react virtualized as there were requirements around enabling complex two-dimensional grid tables. They are also exploring ways to convert the implementation to use the light reaction window in the future.
Results
Table virtualization alone reduced scripting time by 6 seconds (in a Macbook Pro 4x slower + Fast 3G accelerated environment). This was the most impactful performance improvement in the refactoring project.

Before: about 10 seconds of script after user input.

After: 4 seconds of script after user input.
2. Auditoría con APIConcepto de API¿Qué es una API?Una API, siglas de Application Programming Interface o Interfaz de Programación de Apps, es un recopilatorio de código que se puede emplear para que varias apps se comuniquen entre ellas. Es algo que realiza una tarea equivalente a la interfaz de usuario al momento de promover la interacción entre persona y programa, solo que aplicado única y exclusivamente dentro del entorno del software.Aún cuando suene plus User Timing
The AirSHIFT team then refactored the scripts that run with user input. the flame table
from Chrome DevTools
allows you to analyze what is actually happening in the main thread. But the AirSHIFT team found it easier to analyze application activity based on the React lifecycle.
React 16 provides its performance tracking through the
User time API, which you can view from the
Times section
from Chrome DevTools. AirSHIFT used the Times section to find unnecessary logic running in React lifecycle events.

React user time events.
Results
The AirSHIFT team found that a
Reaction Tree Reconciliation
estaba sucediendo justo antes de cada ruta de navegación. Esto significaba que React estaba actualizando la tabla de turnos innecesariamente antes de las navegaciones. Una actualización innecesaria del estado de Redux estaba causando este problema. Arreglarlo ahorró alrededor de 750 ms de tiempo de scripting. AirSHIFT también realizó otras microoptimizaciones que eventualmente llevaron a una reducción total de 1 segundo en el tiempo de programmingConcepto de Programación¿Qué es la Programación?La Programación es el procedimiento al que se recurre para crear algún tipo de aplicación o software, para materializar un concepto o proyecto que requiere de la utilización de un lenguaje informático para poder llevarse a cabo. Es algo que está absolutamente ligado a la figura del programador, y que cada vez está cobrando más relevancia dentro del mundo del marketing.Decimos que tanto esta figura plus.
3. Lazy loading components and costly logic transfer to web workers
AirSHIFT has a built-in chat application. Many store owners communicate with their staff members via chat while looking at the shift table, which means that a user may be typing a message while the table is loading. If the main thread is busy with scripts that are rendering the table, the user input could be annoying.
Para mejorar esta experiencia, AirSHIFT ahora usa React.lazy y Suspense para mostrar marcadores de posición para el contentsEl contenido puede ser muy difícil de definir con precisión. Es una definición que se refiere a las declaraciones contenidas en un documento o publicación de cualquier tipo y puede incluir las tecnologías de la información y la comunicación. Esto cubre todos los tipos de medios como imágenes y texto. A parte de esto, en el campo de la optimización de motores de búsqueda, los términos duplicar contenido, contenido único, plus de la tabla mientras carga lentamente los componentes reales.
The AirSHIFT team also migrated some of the expensive business logic within lazily loaded components to
web workers. This solved the user input jank issue by freeing the main thread so it could focus on responding to user input.
Typically developers are faced with complexity when using workers, but this time Comlink did the heavy lifting for them. Below is the pseudocode of how AirSHIFT worked on one of the most expensive operations they ever had: calculating total labor costs.
In AppConcepto de APP¿Qué es una APP?Una App es todo aquel programa que se ejecuta desde una interfaz teléfono celular, es decir, desde un móvil o una tablet. Consiste en la herramienta principal para cualquier usuario que tenga un teléfono teléfono celular, de todo el software que se mueve en tiendas digitales como Google Play Store o la App Store y que tanto se adentra en cualquier terminal moderno.Es un concepto plus.js, use React.lazy y Suspense para mostrar contenido de respaldo mientras se carga
import React, { lazy, Suspense } desde 'react'
const Hello = lazy(() => import('./Cost'))
const Loading = () => (
<div>Some fallback content to show while loading</div>
)
export default function App({ userInfo }) {
return (
<div>
<Suspense fallback={<Loading />}>
<Cost />
</Suspense>
</div>
)
}
In the Cost component, use comlink to run the calculation logic
import React desde 'react';
import { proxy } desde 'comlink';
const WorkerlizedCostCalc = proxy(new Worker('./WorkerlizedCostCalc.js'));
export default function Cost({ userInfo }) {
const instance = await new WorkerlizedCostCalc();
const cost = await instance.calc(userInfo);
return <p>{cost}</p>;
}
Implement the calculation logic that runs on the worker and expose it with comlink
import { expose } desde 'comlink'
import { someExpensiveCalculation } desde './CostCalc.js'
expose({
calc(userInfo) {
return someExpensiveCalculation(userInfo);
}
}, self);
Results
A pesar de la cantidad limitada de lógica que trabajaron como prueba, AirSHIFT cambió alrededor de 100 ms de su JavaScriptJavaScript es un lenguaje de programación que funciona en el lado del cliente y con el que las webs pueden ser más funcionales. Incorporación en código HTML El código JavaScript puede ser incrustado en las páginas HTML, para que adquieran funcionalidad. Existen varias opciones. Puede estar entre las etiquetas <SCRIPT> y </SCRIPT>, puede estar contenido en un archivo externo, puede ser un parámetro de las etiquetas HTML, y puede estar plus del hilo principal al hilo de trabajo (simulado con aceleración de CPU 4x).

AirSHIFT is currently exploring whether they can lazy load other components and offload more logic to web workers to further reduce jank.
4. Establish a performance budget
With all of these optimizations in place, it was critical to ensure that the application continued to function over time. AirSHIFT now uses pack size no exceder el tamaño de archivo JavaScript y CSSConcepto de CSS¿Qué es el CSS?CSS es un lenguaje de programación que se usa para definir el estilo y el aspecto de un documento que se ha escrito mediante de un lenguaje de etiquetas, como HTML. Conocido además como hojas de estilo en cascada, es el que se emplea para dar colores, indicar tipos de letra o inclusive resaltar aspectos como el espacio entre items para dotar de estilo a plus actual. Además de establecer estos presupuestos básicos, crearon un tablero para mostrar varios percentiles del tiempo de carga de la tabla de turnos para verificar si la aplicación funciona incluso en condiciones no ideales.
- Ahora se mide el tiempo de finalización del script para cada eventConcepto de Evento¿Qué es un Evento?Un Evento es una actividad de carácter social que suele tener cierta proyección a nivel público y, de esta manera, suscita el interés de un determinado sector relacionado con la temática o con la razón por el que se celebra. Es un tipo de acto que suele tener mucha repercusión a nivel empresarial.Podemos hallar distintos tipos de eventos, desde los deportivos hasta los empresariales, pasando plus de Redux
- Performance data is collected in Elasticsearch
- The performance of the 10th, 25th, 50th and 75th percentiles of each event is displayed with Kibana
AirSHIFT is now monitoring the shift table load event to make sure it completes in 3 seconds for 75th percentile users. This is an unapplied budget for now, but they are considering automatic notifications through Elasticsearch when they exceed your budget.

The Kibana dashboard showing daily performance data by percentiles.
Results
In the graph above, you can see that AirSHIFT is now mainly hitting the 3 second budget for 75th percentile users and also loads the shift table in one second for 25th percentile users. By capturing RUM performance data from various conditions and devices, AirSHIFT can now check if a new feature version is really affecting the performance of the application or not.
5. Performance hackathons
While all of these performance optimization efforts were important and impactful, it's not always easy to get engineering and business teams to prioritize non-functional development. Part of the challenge is that some of these performance optimizations cannot be planned. They require experimentation and a trial and error mindset.
AirSHIFT is now conducting internal 1-day performance hackathons to allow engineers to focus only on performance-related work. In these hackathons they remove all limitations and respect the creativity of the engineers, which means that any implementation that contributes to speed is worth considering. To speed up the hackathon, AirSHIFT divides the group into small teams and each team competes to see who can get the biggest Lighthouse performance score improvement. Teams become very competitive! 🔥

Results
The hackathon approach is working well for them.
- Performance bottlenecks can be easily spotted by testing multiple approaches during the hackathon and measuring each with Lighthouse.
- After the hackathon, it's pretty easy to convince the team which optimization they should prioritize for the production release.
- It is also an effective way to defend the importance of speed. All participants can understand the correlation between how you code and how it translates to performance.
A nice side effect was that many other engineering teams within Recruit took an interest in this practical approach and the AirSHIFT team is now facilitating multiple speed hackathons within the company.
Summary
It was definitely not the easiest journey for AirSHIFT to work on these optimizations, but it was certainly worth it. Now AirSHIFT is loading the shift table in 1.5 seconds at the median, which is a 6x improvement over its pre-project performance.
After the performance optimizations were released, one user said:
Thank you very much for speeding up the loading of the shift table. Organizing shift work is much more efficient now.




