Depurando un Bloqueo No Reproducible

Rate this content
Bookmark

POV: Tu aplicación tiene un bloqueo que afecta a miles de usuarios, pero por más que lo intentas, no puedes reproducirlo y no tienes idea de qué lo está causando. Escucha la historia de una lucha épica para vencer un error no reproducible y aprende qué hacer (y qué no hacer) cuando te enfrentes a un enemigo así.

20 min
25 Oct, 2021

Video Summary and Transcription

La charla trata sobre un error grave que causó 20,000 bloqueos en una aplicación de JS. El error fue una excepción de índice fuera de límites en la clase SimplePool. El equipo utilizó un depurador para analizar el error y descubrió una condición de carrera causada por una actualización de React Native SVG. Colaboraron con los contribuyentes de React Native para solucionar el problema y desplegaron una versión parcheada. La charla enfatiza la importancia de utilizar una herramienta de informes de bloqueos, monitorear la salud de las versiones y aprender de los errores y el análisis del código fuente.

Available in English

1. The Story of the Vicious Bug

Short description:

Hoy les contaré una historia, la historia de un error y nuestra lucha contra este error. Un error tan cruel y despiadado que causó nada menos que 20,000 bloqueos. Nuestra tasa de bloqueo aumentó significativamente y nuestra herramienta de informes de bloqueos está reportando una excepción cada minuto. Es un error de excepción de argumento ilegal en una aplicación JS mientras se actualiza una propiedad de estilo en un nodo de sombra de un componente React Native. Esto ocurre para cada usuario, en cada dispositivo Android, y todos los dispositivos Android se ven afectados.

Native. Y nuestra historia comienza en octubre. Somos un equipo de nueve personas y estamos muy felices y orgullosos de lanzar la versión 4.3 de nuestra aplicación. ¿Por qué estamos tan felices y orgullosos? Bueno, porque nos estábamos preparando para nuestro evento en vivo del 11 de octubre que la aplicación estaba cubriendo, y estábamos agregando muchas características esenciales a la aplicación. ¡Genial! Estamos súper felices.

Pero luego, sucede lo inesperado. De repente, nuestra tasa de bloqueo aumenta significativamente. Nuestra herramienta de informes de bloqueos que estamos utilizando, Sentry, está bajo fuego intenso. Está reportando una excepción cada minuto, luego muchas excepciones cada minuto. Básicamente, es una excepción cada segundo y se está volviendo abrumador. Todas esas excepciones son un poco diferentes, pero todas tienen la misma forma. Son así. Básicamente, es un error de excepción de argumento ilegal en una aplicación JS mientras se actualiza una propiedad de estilo en un nodo de sombra de un componente react Native.

Entonces, bueno, el primer pensamiento es, bueno, ya sabes, probamos esta versión, lo probamos mucho. ¿Por qué no vimos que esto estaba sucediendo? Y también, si buscas un poco más sobre este error, tiende a ocurrir si estableces un valor incorrecto para un estilo. Por ejemplo, si establezco el relleno superior como NAN, no es un número, esto es lo que ocurriría. Parece algo bastante fácil de detectar. Entonces, bueno, tal vez solo sucede en ciertos casos extremos que no hemos probado adecuadamente antes. Pero resulta que Sentry está informando que ocurre para cada usuario, cada dispositivo Android, por lo que esto es solo un problema de Android, pero todos los dispositivos Android se ven afectados. Y también en nuestra aplicación puedes favorecer al equipo, por ejemplo, para cambiar un poco la experiencia de la aplicación. Pero no importa qué equipo estés favoreciendo, esto no tiene impacto. Sigues obteniendo el bloqueo.

2. Analyzing the Crash and Reproduction Attempts

Short description:

Tenemos un gran bloqueo al iniciar que afecta a cualquier dispositivo y usuario. No pudimos reproducirlo, así que analizamos la traza de la pila y encontramos una excepción de índice fuera de límites en la clase SimplePool. Retroceder la versión no era una opción, ya que tenía un alto valor para los usuarios. Con una tasa de bloqueo del 10%, intentamos reproducir el problema en varios dispositivos pero no obtuvimos ningún bloqueo.

De acuerdo. Bueno, tenemos un gran bloqueo, tenemos un gran problema que resolver, así que empecemos intentando reproducir el bloqueo, ¿de acuerdo? Afortunadamente, configuramos Sentry o una herramienta de informes de bloqueos para que nos diga qué estaba haciendo el usuario antes de desencadenar el bloqueo. Aquí vemos que el usuario está abriendo la aplicación, iniciando la primera pantalla de la aplicación, que se llama Inicio. Y boom, se bloquea instantáneamente.

De acuerdo, básicamente me estás diciendo que afecta a cualquier dispositivo, se bloquea al iniciar, afecta a cualquier usuario y no podemos reproducirlo. Nunca lo hemos visto antes, ¿cómo es eso posible?

De acuerdo, bueno, supongo que el segundo paso, si no puedes reproducirlo realmente, es analizar la traza de la pila. Así que echemos un vistazo. Vale, dije que tenemos varios errores diferentes. Supongo que veamos el primero. Este es una excepción de índice fuera de límites. Es un error de Java. Ocurre en la clase llamada SimplePool y es una clase de la biblioteca de soporte de Android v4. Y ocurre en SimplePool.release, en la línea 116 de pools.java. Para ser honesto, en este punto ni siquiera sé qué es SimplePool. Ni siquiera sé por qué estoy en el código fuente de Android. Hay un gran problema que resolver y parece que va a llevar mucho tiempo entender qué está pasando porque realmente no entiendo esto. Así que supongo que busquemos una solución más fácil para resolver el problema.

Una idea sería, bueno, ¿podríamos simplemente retroceder nuestra versión? Bueno, si eres un desarrollador de aplicaciones móviles, sabes que no podemos retroceder realmente la versión. En realidad, tenemos que implementar una nueva versión con el código antiguo. Es un poco molesto y significa que ciertos usuarios, ya sabes, los usuarios obtendrán una actualización de la aplicación que revierte todo. En este momento, sabemos que nuestra tasa de bloqueo es del 10%. Parece que básicamente un usuario que abre la aplicación tiene una probabilidad de 1 de cada 10 de bloquear la aplicación. Pero parece que cuando intentan restaurarla, funciona. Además, esta versión tiene un gran valor para los usuarios. Resultó ser una de las versiones con mejor calificación a pesar de este bloqueo excepcional. Así que pensamos, bueno, no retrocedamos. No es el fin del mundo. Es extremadamente grande tener una tasa de bloqueo del 10%, pero intentemos solucionarlo de otra manera. De acuerdo, sabemos que la tasa de bloqueo es del 10%, así que estoy pensando, bien, puedo idear un plan de batalla. Voy a tomar seis dispositivos Android, voy a desencadenar con un script 10 lanzamientos de la aplicación por dispositivo, así que estadísticamente debería obtener entre cinco y diez bloqueos, ¿verdad? Y al menos eso sería algún tipo de reproducción. Finalmente podría ver el problema y si obtengo una solución, podría probarla. El resultado fue que no obtuve ningún bloqueo.

3. Investigando las Dependencias Nativas y las Pruebas

Short description:

Nuestra versión anterior no se bloqueaba, esta versión se bloquea. Actualizamos dos dependencias nativas: React Native SVG y navegación nativa. Sospechamos que la navegación nativa es la culpable de los bloqueos. Podemos lanzar una nueva versión al 10% de nuestros usuarios para probar si la nueva versión soluciona el bloqueo. Si no lo hace, podemos retroceder la biblioteca SVG. Si ninguna de las soluciones soluciona el bloqueo, podría llevar a desinstalaciones potenciales.

Ninguna en absoluto. Bastante desafortunado. Bueno, supongo que necesitamos encontrar algo más. Otra idea fue qué cambió realmente. Nuestra versión anterior no se bloqueaba, esta versión se bloquea. Entonces, ¿qué introdujimos entre las dos versiones que realmente bloqueó la aplicación?

Entonces, mi idea en este punto fue echar un vistazo a las dependencias nativas que actualizamos. Porque bueno, esta es una excepción de Java, por lo que ocurre en el código nativo, por lo que probablemente el culpable sea una dependencia nativa que actualizamos. Resulta que actualizamos dos dependencias nativas desde la última versión. La primera fue React Native SVG, y la segunda fue la navegación nativa. Probablemente no conozcas la navegación nativa. En realidad, es un fork que hicimos de una biblioteca de navegación de Airbnb, que utiliza, bueno, navegación nativa. Resulta que nosotros mismos agregamos algunas características para mejorar el rendimiento al inicio, ¿verdad? Suena como un buen culpable, ya sabes, lo actualizamos para mejorar el rendimiento al inicio, obtenemos bloqueos al inicio. Vale, parece que este debería ser el culpable detrás de nuestros bloqueos.

Como sabrás, en Play Store, puedes lanzar una nueva versión de tu aplicación solo para un subconjunto de tus usuarios. Por ejemplo, puedes lanzar la nueva versión solo para el 10% de tus usuarios. Esto nos permite idear un nuevo plan de batalla. Si la navegación nativa es realmente la culpable, podemos probarlo. No creamos la navegación nativa. Lanzamos una nueva versión que lanzamos solo para el 10% de nuestros usuarios. Volvemos a verificar, deberíamos poder ver en aproximadamente una hora si la nueva versión es exitosa. Y si tiene éxito, luego la lanzamos para todos, la nueva versión porque, bueno, el bloqueo está solucionado, ¡yay! Pero, ¿qué pasa si en realidad no soluciona el bloqueo? Bueno, supongo que en este caso, retrocedamos la otra, la biblioteca SVG, y bueno, hacemos lo mismo. Lanzamos para el 10% de nuestros usuarios. Volvemos a verificar. Si es exitoso, yay, lanzamiento completo, ok, genial, ganamos. Pero, ¿qué pasa si nuevamente eso no soluciona el bloqueo? Esto significaría que si aún no soluciona el bloqueo, significaría que actualizamos dos veces nuestra aplicación y cada vez, cada vez, el 10% de nuestros usuarios obtuvo una actualización que en realidad no hizo nada y no solucionó el bloqueo. Eso es realmente una fuente de desinstalación potencial, como cuando un usuario recibe muchas actualizaciones de su aplicación pero no hace nada por él. A veces sucede que un usuario desinstala la aplicación debido a esto. Para ser honesto, ese plan es sí, es un poco tonto.

4. Analyzing the Bug and Using the Debugger

Short description:

Nuestro error fue una excepción de índice fuera de límites en la clase SimplePool. Intentamos acceder a un array en el índice mPoolSize, que era -1. El único lugar donde mPoolSize cambia es en la función acquire, y está protegido para que no sea inferior a cero. Decidimos utilizar el depurador para investigar más a fondo.

De acuerdo. Supongo que en este punto, sí, necesitamos ir más profundo. Realmente necesitamos entender el error y analizarlo. Así que echemos otro vistazo. Nuestro error, como recordarás, fue una excepción de índice fuera de límites en un array. De acuerdo. Veamos dónde estaba ocurriendo. Estaba ocurriendo, como quizás recuerdes, en una clase llamada SimplePool dentro del código de la biblioteca de soporte Android v4. Y básicamente el error fue este. Tenemos un array de objetos llamado mPool y tenemos un índice llamado mPoolSize y estamos intentando acceder a este array en el índice mPoolSize que aparentemente es igual a menos uno. Así que ahora no necesitas ser un experto desarrollador de Java para saber que acceder a un array en el índice menos uno no es una buena idea. Así que puedes entender de dónde viene el bloqueo. El valor de mPoolSize es menos uno, lo cual no es bueno. Entonces la pregunta ahora es qué puede modificar realmente mPoolSize. mPoolSize solo se modifica en este lugar. Se inicializa en diez y luego solo se reduce en esta función llamada acquire dentro de SimplePool. Este es el único lugar donde mPoolSize realmente cambia en esta función y se reduce pero puedes notar algo allí, en realidad hay una condición para protegerlo de ser inferior a cero. Aquí está, si mPoolSize es mayor que cero, entonces se reduce mPoolSize. Así que suena imposible que mPoolSize se convierta en menos uno porque si mPoolSize es cero, no puedes reducirlo aún más, así que eso realmente suena imposible.

5. Analyzing the Bug with the Debugger

Short description:

Utilizamos el depurador en Android Studio para analizar la función acquire en el código de React Native. Descubrimos que la función dynamic de map create podía ser llamada desde diferentes hilos, lo que provocaba una condición de carrera. La actualización de SVG causó el error.

De acuerdo, supongo que es hora de sacar nuestra arma definitiva y, por supuesto, estoy hablando del depurador, el arma definitiva contra los errores. Así que bien, abramos Android Studio y veamos la famosa función que en realidad disminuye mPoolSize, que es la función acquire, y en las trazas de pila que estábamos viendo, veíamos que esta función era llamada desde el código de React Native en la clase llamada dynamic de map y la función create. Exactamente esta línea, así que, bien, pongamos un punto de interrupción ahí. La primera vez que se activó el punto de interrupción, básicamente ejecuté la aplicación y bueno, llegué al primer punto de interrupción bastante rápido y me está diciendo básicamente que, en realidad, dynamic de map es utilizado por React Native para almacenar propiedades de estilo de componente. Aquí estamos actualizando el ancho de un cierto componente. Así que puedes imaginar que esto va a suceder mucho porque, básicamente, cada vez que modificamos un estilo, llegamos al punto de interrupción. Así que sí, el segundo punto de interrupción fue bastante similar y en realidad, sí, hice clic básicamente 34 veces en el botón de reproducción y obtuve resultados similares pero, oh, en realidad, una revelación en el clic número 34 porque desde el primer clic hasta el 33, estoy obteniendo algo como esto, en el clic 34, estoy obteniendo algo como esto. Hay una diferencia muy sutil en esos puntos de interrupción porque desde el primer clic hasta el 33, los hilos que Android Studio estaba reportando son MQT native modules y bueno, este es el hilo que que React Native suele usar para trabajar con código nativo a través del puente.

6. Analyzing the Bug and Fixing the Issue

Short description:

En el hito 34, se utilizó el hilo principal, lo que dio una gran pista. La función dynamic de map create puede ser llamada desde diferentes hilos. El error fue causado por la actualización de SVG, donde ocurrió una condición imposible debido a la seguridad del hilo. Lo solucionamos colaborando con los contribuyentes de React Native y desplegando una versión parcheada para el 10% de nuestros usuarios. Lección aprendida: Utiliza tu herramienta de informes de errores de manera exhaustiva y configúrala para capturar las acciones del usuario.

Pero en el hito 34, el hilo que se utilizó fue el hilo principal, por lo que básicamente esto significa que en este caso no estaba activando el error, pero esto me dio una pista muy importante. Esta función dynamic de map create podría ser llamada desde diferentes hilos. Si observamos el hito 34, en realidad notamos que en este caso la propiedad que se estaba actualizando era una propiedad llamada fill, y bueno, esto realmente no suena como una propiedad de estilo de React Native, ¿verdad? De hecho, es una propiedad de SVG. Así que fue la actualización de SVG la que causó este error. Veamos qué puede suceder.

Entonces, React Native SVG, lo actualizamos a la versión 7 y comenzaron a utilizar este código dynamic de app create para mejorar el rendimiento de las animaciones SVG nativas. Pero lo estaban utilizando desde el hilo principal mientras que React Native lo estaba utilizando desde los módulos nativos MQT. Entonces, ¿qué puede suceder en realidad? Esta condición imposible, bueno, cuando tienes algo imposible sucediendo en Java, generalmente es debido a la seguridad del hilo. Como desarrolladores de JavaScript, no estamos acostumbrados a lidiar con múltiples hilos, pero cuando usas React Native, también tienes Java en la mezcla. Así que tienes seguridad de hilos en la mezcla. Aquí, esta condición imposible, podría suceder que dos hilos, hilo A y hilo B, pudieran ir prácticamente al mismo tiempo en la condición si amplesize es mayor que cero y pensar que es mayor que cero, y luego ambos ingresan a la condición al mismo tiempo, lo que significa que ambos lo disminuyen. Es algo así. El hilo A ve que amplesize es mayor que cero, genial, pero no tiene tiempo para disminuirlo aún, no tiene tiempo para salir de la función porque el hilo B también está ingresando a la condición y verificando que amplesize es mayor que cero. Y si al principio amplesize es uno, entonces vuelve a ser uno cuando verificamos la condición para el hilo B. Y luego, lo que sucede es que ambos disminuyen amplesize, por lo que se convierte en cero y luego en menos uno. ¡Vaya, realmente sabemos de dónde viene esto y por eso fue tan difícil de reproducir, porque esta es una condición de carrera que fue muy difícil de activar! Así que arreglemos esto.

Cuando investigamos, encontramos que había una solicitud de extracción en React Native que trataba esto, tratando la seguridad del hilo en dynamic de map create. Y así, en colaboración con el contribuyente principal de React Native que presentó la solicitud de extracción y los mantenedores de React Native SVG, ideamos un plan de batalla final. Parcheamos React Native localmente, desplegamos esta versión para el 10% de nuestros usuarios solo para verificar, y luego, por supuesto, verificamos nuevamente. ¿Fue exitoso? Sí. Finalmente. Lo arreglamos y nuestra tasa de fallos volvió a la normalidad. ¡Hurra! Muy bien. Esto fue fantástico. Pero tal vez algunas lecciones aprendidas de esto. La primera es esta. Debes utilizar tu herramienta de informes de fallos de manera exhaustiva y configurarla para poder utilizarla, porque vas a tener fallos en producción y probablemente vas a tener fallos que no puedes reproducir. Por lo tanto, debes saber qué está haciendo el usuario antes de activar el fallo. Por defecto, es posible que no tengas esto en tu herramienta de informes de fallos, así que debes configurarlo para que sea fácil ver, por ejemplo, las pantallas a las que está navegando tu usuario.

7. Detalles del Usuario, Salud de la Versión y Aprendizaje

Short description:

Debes agregar detalles sobre el usuario, monitorear la salud de la versión y proteger a tus usuarios. Implementar versiones a un 10% de los usuarios permite monitorear y minimizar el impacto. Profundizar en los errores y el código fuente brinda valiosas experiencias de aprendizaje.

También debes agregar tantos detalles sobre el usuario como sea posible, por supuesto, de manera compatible con el RGPD. Por ejemplo, en nuestro caso, agregar qué equipos el usuario estaba marcando como favoritos para cambiar su experiencia, porque a veces activas errores solo en ciertos casos en tu aplicación, por supuesto.

Luego, por supuesto, debes monitorear la salud de tu versión. Una tasa de fallos del 10%, por supuesto, es excepcional. Es realmente, realmente malo. Una tasa de fallos del 0.2% es un poco mejor. El estándar del mercado es de aproximadamente 0.3, 0.4 para Android. Es aún más bajo para iOS.

Y si realmente haces eso, también te permite hacer una cosa, proteger a tus usuarios. Y eso es lo que hicimos después de esto. Cada vez que implementamos una nueva versión, en realidad la lanzamos para el 10% de nuestros usuarios. Por supuesto, nunca deberíamos tener fallos, fallos excepcionales como este en esos 10%, pero en caso de que realmente suceda, al menos solo afectamos al 10% de nuestros usuarios. Entonces, el resto de los usuarios no tienen impacto. Y, por supuesto, eso significa que puedes saber si la versión fue exitosa, por lo que puedes monitorear la salud de tu versión.

Y, por supuesto, tienes tiempo entre la implementación inicial y, por ejemplo, en nuestro caso, tuvimos el evento en vivo el 11 de octubre. Hicimos la implementación el 9 de octubre. No fue realmente una buena idea.

El último punto es este. Puedes aprender mucho profundizando. Nunca he aprendido tantas cosas como cuando estaba investigando un error que no podía reproducir, y me sumergí más profundamente en el código fuente de las bibliotecas que estaba usando, y cada vez, aprendí mucho.

Y eso es todo. Gracias por ver, y contáctame si tienes alguna pregunta en el canal de Discord o en Twitter. Gracias.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

React Advanced Conference 2021React Advanced Conference 2021
39 min
Don't Solve Problems, Eliminate Them
Top Content
Humans are natural problem solvers and we're good enough at it that we've survived over the centuries and become the dominant species of the planet. Because we're so good at it, we sometimes become problem seekers too–looking for problems we can solve. Those who most successfully accomplish their goals are the problem eliminators. Let's talk about the distinction between solving and eliminating problems with examples from inside and outside the coding world.
JSNation 2023JSNation 2023
29 min
Modern Web Debugging
Few developers enjoy debugging, and debugging can be complex for modern web apps because of the multiple frameworks, languages, and libraries used. But, developer tools have come a long way in making the process easier. In this talk, Jecelyn will dig into the modern state of debugging, improvements in DevTools, and how you can use them to reliably debug your apps.
React Day Berlin 2022React Day Berlin 2022
22 min
Jotai Atoms Are Just Functions
Top Content
Jotai is a state management library. We have been developing it primarily for React, but it's conceptually not tied to React. It this talk, we will see how Jotai atoms work and learn about the mental model we should have. Atoms are framework-agnostic abstraction to represent states, and they are basically just functions. Understanding the atom abstraction will help designing and implementing states in your applications with Jotai
TechLead Conference 2023TechLead Conference 2023
35 min
A Framework for Managing Technical Debt
Let’s face it: technical debt is inevitable and rewriting your code every 6 months is not an option. Refactoring is a complex topic that doesn't have a one-size-fits-all solution. Frontend applications are particularly sensitive because of frequent requirements and user flows changes. New abstractions, updated patterns and cleaning up those old functions - it all sounds great on paper, but it often fails in practice: todos accumulate, tickets end up rotting in the backlog and legacy code crops up in every corner of your codebase. So a process of continuous refactoring is the only weapon you have against tech debt.In the past three years, I’ve been exploring different strategies and processes for refactoring code. In this talk I will describe the key components of a framework for tackling refactoring and I will share some of the learnings accumulated along the way. Hopefully, this will help you in your quest of improving the code quality of your codebases.

React Summit 2023React Summit 2023
24 min
Debugging JS
As developers, we spend much of our time debugging apps - often code we didn't even write. Sadly, few developers have ever been taught how to approach debugging - it's something most of us learn through painful experience.  The good news is you _can_ learn how to debug effectively, and there's several key techniques and tools you can use for debugging JS and React apps.
React Day Berlin 2022React Day Berlin 2022
29 min
Fighting Technical Debt With Continuous Refactoring
Top Content
Let’s face it: technical debt is inevitable and rewriting your code every 6 months is not an option. Refactoring is a complex topic that doesn't have a one-size-fits-all solution. Frontend applications are particularly sensitive because of frequent requirements and user flows changes. New abstractions, updated patterns and cleaning up those old functions - it all sounds great on paper, but it often fails in practice: todos accumulate, tickets end up rotting in the backlog and legacy code crops up in every corner of your codebase. So a process of continuous refactoring is the only weapon you have against tech debt. In the past three years, I’ve been exploring different strategies and processes for refactoring code. In this talk I will describe the key components of a framework for tackling refactoring and I will share some of the learnings accumulated along the way. Hopefully, this will help you in your quest of improving the code quality of your codebases.

Workshops on related topic

React Summit 2023React Summit 2023
170 min
React Performance Debugging Masterclass
Featured WorkshopFree
Ivan’s first attempts at performance debugging were chaotic. He would see a slow interaction, try a random optimization, see that it didn't help, and keep trying other optimizations until he found the right one (or gave up).
Back then, Ivan didn’t know how to use performance devtools well. He would do a recording in Chrome DevTools or React Profiler, poke around it, try clicking random things, and then close it in frustration a few minutes later. Now, Ivan knows exactly where and what to look for. And in this workshop, Ivan will teach you that too.
Here’s how this is going to work. We’ll take a slow app → debug it (using tools like Chrome DevTools, React Profiler, and why-did-you-render) → pinpoint the bottleneck → and then repeat, several times more. We won’t talk about the solutions (in 90% of the cases, it’s just the ol’ regular useMemo() or memo()). But we’ll talk about everything that comes before – and learn how to analyze any React performance problem, step by step.
(Note: This workshop is best suited for engineers who are already familiar with how useMemo() and memo() work – but want to get better at using the performance tools around React. Also, we’ll be covering interaction performance, not load speed, so you won’t hear a word about Lighthouse 🤐)
React Advanced Conference 2021React Advanced Conference 2021
174 min
React, TypeScript, and TDD
Top Content
Featured WorkshopFree
ReactJS is wildly popular and thus wildly supported. TypeScript is increasingly popular, and thus increasingly supported.

The two together? Not as much. Given that they both change quickly, it's hard to find accurate learning materials.

React+TypeScript, with JetBrains IDEs? That three-part combination is the topic of this series. We'll show a little about a lot. Meaning, the key steps to getting productive, in the IDE, for React projects using TypeScript. Along the way we'll show test-driven development and emphasize tips-and-tricks in the IDE.
React Advanced Conference 2021React Advanced Conference 2021
145 min
Web3 Workshop - Building Your First Dapp
Top Content
Featured WorkshopFree
In this workshop, you'll learn how to build your first full stack dapp on the Ethereum blockchain, reading and writing data to the network, and connecting a front end application to the contract you've deployed. By the end of the workshop, you'll understand how to set up a full stack development environment, run a local node, and interact with any smart contract using React, HardHat, and Ethers.js.
React Summit 2022React Summit 2022
136 min
Remix Fundamentals
Top Content
Featured WorkshopFree
Building modern web applications is riddled with complexity And that's only if you bother to deal with the problems
Tired of wiring up onSubmit to backend APIs and making sure your client-side cache stays up-to-date? Wouldn't it be cool to be able to use the global nature of CSS to your benefit, rather than find tools or conventions to avoid or work around it? And how would you like nested layouts with intelligent and performance optimized data management that just works™?
Remix solves some of these problems, and completely eliminates the rest. You don't even have to think about server cache management or global CSS namespace clashes. It's not that Remix has APIs to avoid these problems, they simply don't exist when you're using Remix. Oh, and you don't need that huge complex graphql client when you're using Remix. They've got you covered. Ready to build faster apps faster?
At the end of this workshop, you'll know how to:- Create Remix Routes- Style Remix applications- Load data in Remix loaders- Mutate data with forms and actions
Vue.js London Live 2021Vue.js London Live 2021
169 min
Vue3: Modern Frontend App Development
Top Content
Featured WorkshopFree
The Vue3 has been released in mid-2020. Besides many improvements and optimizations, the main feature of Vue3 brings is the Composition API – a new way to write and reuse reactive code. Let's learn more about how to use Composition API efficiently.

Besides core Vue3 features we'll explain examples of how to use popular libraries with Vue3.

Table of contents:
- Introduction to Vue3
- Composition API
- Core libraries
- Vue3 ecosystem

Prerequisites:
IDE of choice (Inellij or VSC) installed
Nodejs + NPM
JSNation 2023JSNation 2023
174 min
Developing Dynamic Blogs with SvelteKit & Storyblok: A Hands-on Workshop
Featured WorkshopFree
This SvelteKit workshop explores the integration of 3rd party services, such as Storyblok, in a SvelteKit project. Participants will learn how to create a SvelteKit project, leverage Svelte components, and connect to external APIs. The workshop covers important concepts including SSR, CSR, static site generation, and deploying the application using adapters. By the end of the workshop, attendees will have a solid understanding of building SvelteKit applications with API integrations and be prepared for deployment.