Compartir es Cuidar: ¿Deberían los Micro Frontends Compartir Estado?

Rate this content
Bookmark

La arquitectura de micro frontends es extremadamente poderosa cuando se trata de dividir grandes monolitos frontends en bloques más pequeños y desplegables de forma individual, cada uno propiedad de un equipo autónomo y enfocado en un dominio empresarial. Pero, ¿qué pasa con el Estado? A menudo se nos dice que los micro frontends no deben compartir estado, ya que esto los acoplaría entre sí. Sin embargo, cuando se trata de interfaces de usuario complejas, no es raro encontrarse con escenarios donde es necesario gestionar el estado entre micro frontends. Esta charla trata sobre encontrar el punto óptimo: ¿En qué escenarios es razonable que los micro frontends compartan estado? ¿Y cómo deberían compartir estado los micro frontends manteniéndose desacoplados entre sí? Discutimos y comparamos diferentes soluciones en React.

23 min
21 Jun, 2022

Video Summary and Transcription

Los micro frontends permiten que los equipos de desarrollo trabajen de forma autónoma y con menos fricciones y limitaciones. Organizar los equipos en torno a preocupaciones empresariales, en línea con los subdominios, en lugar de preocupaciones técnicas, puede llevar a un software bien dividido y a historias de usuario bajo la responsabilidad de un solo equipo. Tener un respaldo o punto de referencia lógico es importante para implementar micro frontends sin romper su aislamiento. Los micro frontends pueden comunicarse entre sí utilizando el objeto window y eventos personalizados. Los micro frontends deben mantenerse aislados mientras mantienen la comunicación a través de diversos enfoques.

Available in English

1. Introducción a los Micro-frontends

Short description:

Los Micro-frontends permiten que los equipos de desarrollo trabajen de manera autónoma y con menos fricciones y limitaciones. Exploraremos una perspectiva orientada al dominio para comprender la comunicación entre los micro-frontends. Resolver las historias de usuario debería ser una tarea de extremo a extremo de un solo equipo, en lugar de ser compartida entre varios equipos. Las historias de usuario se organizan según los subdominios.

Hola a todos. Mi nombre es Eliran Atan. Esta es mi segunda vez en React Summit, pero aún estoy muy emocionado. He estado construyendo sistemas escalables durante la última década, y hoy quiero centrarme en los micro-frontends, y especialmente en el intercambio de estado de los micro-frontends.

Entonces, los micro-frontends se tratan de dividir este monolito de frontend en piezas más pequeñas y manejables que permiten que los equipos de desarrollo trabajen de manera más eficiente y efectiva. Esto se debe a que los micro-frontends suelen estar aislados entre sí. Permiten que los equipos de desarrollo trabajen de manera autónoma y con menos fricciones y limitaciones.

Un problema común que surge cuando hablamos de micro-frontends es si deben compartir estado o comunicarse de alguna manera. Si es así, ¿cómo deberíamos hacerlo sin romper su aislamiento entre sí? En esta charla veremos un enfoque diferente para pensar en los micro-frontends. Vamos a abordar eso desde una perspectiva orientada al dominio. Veremos cómo podemos representar un micro-frontend utilizando algo que llamamos un contexto acotado. El contexto acotado es esta entidad lógica que refleja nuestra implementación y puede derivar la implementación. Y veremos cómo eso puede ayudarnos a comprender la comunicación entre los micro-frontends.

Entonces, empecemos desde otro ángulo. Hablemos de Agile. En Agile, a menudo trabajamos con historias de usuario. Las historias de usuario son esta breve descripción de un objetivo final que el usuario desea lograr, ¿verdad? Y siempre se describe desde la perspectiva del usuario y en términos de el negocio. Por lo general, en muchas organizaciones, resolver una historia de usuario implicará la cooperación y coordinación de equipos de múltiples capas. Y eso se debe a que el código afectado para resolver esa historia a menudo se comparte entre estos equipos. Y eso se debe a cómo las organizaciones tienden a estructurar los equipos, especialmente cuando hablamos de front-end. A menudo vemos esta división arbitraria de responsabilidades entre equipos. A veces se trata de ser dueño de componentes o páginas o vistas. Pero eso no es realmente cómo se organizan las historias de usuario. Lo que realmente queremos es alguna forma de organizar nuestros equipos y código de manera que resolver una historia de usuario sea una tarea de extremo a extremo de un solo equipo. Eso significa que el código afectado para resolver esa historia pertenecería a un solo equipo determinado. Eso hará que el flujo sea mucho mejor, especialmente a gran escala. Una pregunta que debemos hacernos es cómo se organizan las historias de usuario. Desde una perspectiva orientada al dominio, las historias de usuario se organizan según los subdominios. Si tomamos una aplicación de e-commerce estándar, ese es el dominio más simple que podemos pensar, entonces una división normal en subdominios sería algo como catálogo, pedido, entrega, soporte y tal vez algunos otros subdominios. El subdominio del catálogo se ocupa de permitir a los usuarios navegar y buscar productos, mientras que los otros subdominios se ocupan de que los usuarios agreguen productos a

2. Implementación y Comunicación de Microfrontends

Short description:

Organizar equipos en torno a preocupaciones comerciales, alineados con subdominios en lugar de preocupaciones técnicas, puede llevar a un software dividido de manera ordenada y a historias de usuario bajo la responsabilidad de un solo equipo. Los microfrontends mejoran la segregación entre subdominios y brindan autonomía a los equipos sobre la pila tecnológica. El diseño impulsado por el dominio, específicamente el DDD estratégico, ayuda a descomponer el dominio en subdominios. Cada contexto acotado deriva una implementación de un microfrontend, simplificando la implementación y mejorando la comunicación. La herramienta de mapeo de contexto ayuda a comprender las relaciones entre diferentes contextos y permite una comunicación efectiva entre los microfrontends.

subtarjetas y solicitar la entrega. Lo que podemos hacer es organizar los equipos según las preocupaciones comerciales, alineados con los subdominios en lugar de las preocupaciones técnicas como componentes, páginas o vistas, y así sucesivamente. Junto con la ley de Conway, que establece que las organizaciones tienden a reflejar su propia estructura en el software que construyen, es muy probable que obtengamos un software dividido de manera ordenada y que las historias de usuario probablemente caigan bajo la responsabilidad de un solo equipo.

Ahora, esto se puede llevar más lejos, y aquí es donde hablamos nuevamente de los microfrontends. Al dividir este monolito en diferentes microfrontends, mejoraremos la segregación entre subdominios y daremos a los equipos otro nivel de autonomía en el nivel de la pila tecnológica, ya que ahora pueden elegir sus propias herramientas y patrones de diseño, por ejemplo. Cada equipo puede optimizar los patrones de diseño que utiliza para los objetivos específicos que desea lograr.

Entonces, mi punto aquí es que una base sólida para los microfrontends es considerar la alineación con los aspectos comerciales. Es por eso que cuando hablamos de microfrontends, debemos pensar en el diseño impulsado por el dominio, específicamente en el DDD estratégico. El DDD estratégico es esta herramienta que nos permite descomponer correctamente nuestro dominio en varios subdominios de una manera que maximice el potencial que tiene el microfrontend. El DDD realmente nos dice que debemos reunir a nuestros expertos en el dominio para tomar el tiempo y hacer una lluvia de ideas junto con otras partes interesadas para formar este lenguaje inequívoco que realmente capture las entidades y procesos naturales que ocurren dentro de este subdominio. Y esta forma de lenguaje forma un límite lógico que llamamos contexto acotado. El contexto acotado tiene mucho que ofrecer, muchos beneficios para trabajar con el contexto acotado y derivar de él la implementación real del microfrontend. Entonces, cada contexto acotado derivará una implementación de un cierto microfrontend. Podríamos resumir eso diciendo que un microfrontend es una implementación técnica de un contexto acotado. Por lo tanto, tener un contexto acotado que deriva microfrontends tiene numerosos beneficios. El contexto acotado puede simplificar drásticamente la implementación de cada microfrontend porque cada término en cada contexto acotado se describe desde la perspectiva de ese contexto acotado. Por lo tanto, no tienes mucha información redundante que debas manejar. Solo manejas las cosas relevantes dentro de ese contexto. Y hay un beneficio más profundo en eso. Y ahora tenemos esto en cada contexto, tenemos un lenguaje cohesivo inequívoco que todos entienden. Y eso mejora mucho la comunicación. Y eso hace que traducir las historias de usuario sea mucho más fácil, y así sucesivamente.

Pero quiero centrarme en otro beneficio que se relaciona con cómo debe comunicarse un microfrontend. Tenemos otra herramienta que forma parte del kit de herramientas del DDD, que es la herramienta de mapeo de contexto. El mapeo de contexto se trata de comprender, hacer una lluvia de ideas y comprender las relaciones entre diferentes contextos. Por ejemplo, aunque el término `producto` generalmente significa otra cosa cuando hablamos del contexto del catálogo, por ejemplo, una estructura que muestra todos los comentarios, reseñas, detalles del producto, imágenes del producto, y así sucesivamente, eso significa que `producto` significará otra cosa en el contexto del pedido. Probablemente tendrá algún identificador, precio, descuentos o todo lo que se relacione con el pedido. Pero aún así, aunque estén definidos de manera diferente en esos diferentes contextos, aún tienen esta conexión lógica entre ellos, ¿verdad? Porque queremos permitir a los usuarios agregar productos que encuentren en el catálogo a algún carrito que es naturalmente parte del contexto del pedido. Y eso realmente genera una comunicación que debemos tener entre el frontend del catálogo y el frontend del pedido, ¿verdad? Esos fragmentos de información, un producto seleccionado, deben comunicarse entre estos microfrontends. Entonces, aquí vemos una forma de comprender lógicamente cuáles son las conexiones que debemos hacer entre los contextos, y luego derivar a partir de ahí la comunicación entre la implementación, entre los microfrontends reales. Y eso puede ayudarnos a evitar comunicaciones innecesarias, y también puede ayudarnos a comprender si nuestro modelo es correcto, si no estamos creando demasiado

3. Implementación de la Comunicación entre Microfrontends

Short description:

Tener una copia de seguridad lógica o un punto de referencia es importante para implementar microfrontends sin romper su aislamiento. Utilizar el backend para comunicar productos seleccionados manteniendo el aislamiento es un enfoque directo. Sin embargo, esto puede llevar a desventajas en la experiencia del usuario y a una complejidad del frontend trasladada al backend, lo que causa cuellos de botella en el desarrollo.

mucha comunicación, y así sucesivamente. Por lo tanto, creo que es muy importante tener alguna copia de seguridad lógica o un punto de referencia para sus implementaciones. Ahora, una vez que tenemos este punto de referencia, entendemos cómo mapear estas comunicaciones, nos gustaría hablar sobre cómo implementar técnicamente una comunicación entre microfrontends, y especialmente sin romper su aislamiento entre sí, sin acoplarlos. Entonces, una respuesta directa a eso sería, bueno, no tengamos esta comunicación directa entre microfrontends, usemos el backend. Básicamente, estamos trasladando nuestro estado al backend, y un microfrontend de catálogo podría comunicar los productos seleccionados al backend, mientras que cualquier otro microfrontend interesado en esa información podría consumir esa información. Y esto es muy bueno porque los microfrontends siguen estando aislados entre sí. El problema es que, bueno, si tienes muchos microfrontends, diferentes microfrontends en la misma vista, entonces probablemente tengas alguna desventaja en la experiencia del usuario porque llamar al backend es más lento. Se siente menos eficiente. Otro problema es que estamos trasladando una complejidad del frontend al backend, donde realmente no pertenece. Por lo tanto, también genera problemas, cuellos de botella en el desarrollo porque ahora los desarrolladores de frontend están bloqueados por los desarrolladores de backend cada vez que tienen que hacer algún cambio.

4. Comunicación Directa Entre Microfrontends

Short description:

Los microfrontends pueden comunicarse entre sí utilizando el objeto window y eventos personalizados. Para gestionar estados complejos, se puede utilizar un almacén centralizado de Redux, con cada microfrontend teniendo su propio almacén. Otra opción es permitir que los microfrontends se suscriban o vean los almacenes de otros microfrontends sin la capacidad de modificarlos. Para garantizar la seguridad y la alineación, se puede implementar un almacén global, con cada microfrontend implementando una API específica. En resumen, los microfrontends deben mantenerse aislados mientras mantienen la comunicación a través de diversos enfoques.

Entonces, hablemos sobre la comunicación directa entre microfrontends. Este es un problema muy común en la ingeniería de software. Tenemos estas unidades diferentes que son independientes entre sí. No queremos que estén acopladas entre sí, pero aún así tienen que intercambiar mensajes entre sí porque son parte de un equipo más grande.

Si observamos lo que estamos haciendo en el diseño de software de backend, generalmente se trata de microservicios y microfrontend. Los microservicios y los microfrontend tienen cierta correlación entre ellos. Esa es una oportunidad para aprender mucho sobre los microfrontends. Entonces, si observamos cómo se comunican los microservicios, uno de los mecanismos más populares y poderosos es el mecanismo de suscripción pública, la mensajería asíncrona. Cada microservicio puede publicar información interesante que sucede dentro del microservicio en un espacio compartido, como un bus de mensajes, y cualquier otro microservicio puede consumir esta información en caso de que sea realmente interesante. Esto hace que los microservicios sigan estando desacoplados entre sí de alguna manera, pero aún permite una comunicación muy agradable y poderosa. ¿Podríamos derivar de eso una solución para nuestros microfrontends, verdad? Podríamos usar el objeto window, que es un gran espacio común con el que cada microfrontend puede comunicarse. Y cada microfrontend podría publicar eventos interesantes sobre cosas que suceden, como un producto que se seleccionó para la tarjeta, y cualquier otro microfrontend podría consumir esta información. Entonces, los diferentes microfrontends no son conscientes entre sí, pero aún pueden pasar información importada. Esto se puede implementar de manera muy fácil e incluso nativamente utilizando eventos personalizados. Podemos crear eventos personalizados y enviarlos al objeto window, y podemos agregar escuchadores de eventos al objeto window para obtener esta información de vuelta. Por lo tanto, podrías envolver ese mecanismo con tu framework de React o Vue y construir algo más avanzado que pueda ayudarte a automatizar parte de esta comunicación o hacerla más robusta.

Ahora, eso fue bueno, pero a veces, simplemente tienes que tener un estado. Entonces, comunicarse con el evento es genial, pero hay algunas operaciones complejas o algunas construcciones de datos complejas que queremos tener compartidas o algún tipo de estados como un estado de Redux para gestionar el proceso, y eso puede suceder con bastante frecuencia. Entonces, lo que querríamos es un almacén centralizado de Redux y cada microfrontend podría comunicarse con él para mantener este tipo de estados complejos. Y esto es muy problemático, especialmente cuando hablamos de microfrontends, porque rompe por completo el aislamiento que tienen entre sí, especialmente porque son propiedad de diferentes equipos. Entonces, si el microfrontend de producto manipulara el estado de alguna manera, entonces el microfrontend de entrega y el microfrontend de soporte tendrían que adaptarse o comprender el cambio y eso puede volverse muy difícil. Entonces, lo que realmente queremos son estos almacenes alineados. Tenemos un almacén por microfrontend. Cada microfrontend puede usar ese almacén como un almacén de Redux, y estos almacenes están desacoplados entre sí. Pero, por supuesto, aquí no hay ninguna comunicación entre ellos y eso también es problemático. Otra solución que he visto para mantener un estado entre microfrontends de una manera que aún los mantiene bastante desacoplados es permitir que los microfrontends se suscriban o vean los almacenes de otros microfrontends, pero sin la capacidad de modificar estos almacenes. Entonces, en este ejemplo, el microfrontend de soporte realmente puede ver el almacén del microfrontend de producto y el microfrontend de entrega, pero aún hay algunos problemas aquí, porque cualquier cambio en cómo se implementa el almacén de soporte afectaría a los microfrontends de entrega y producto. Entonces, lo que podemos hacer para que sea aún más seguro es idear este almacén global. Este almacén global gestiona los diferentes almacenes de los diferentes microfrontends, cada microfrontend puede suscribirse al almacén, tiene su propio almacén que puede manipular, y otros microfrontends pueden consumir y suscribirse a sus propios almacenes u otros almacenes. Debido a que este almacén global expondría una API específica, cada microfrontend solo tendría que implementar esa API específica y eso facilitaría todo mucho más, alineando esta API en esos diferentes microfrontends.

Bueno, eso fue una descripción general de tres formas comunes de mantener la comunicación entre microfrontends mientras los mantenemos bastante aislados entre sí. Me gustaría resumir la charla y lo primero que decimos es que debemos esforzarnos por tener equipos altamente autónomos, debemos estructurar los equipos en alineación con los subdominios comerciales y eso no se relaciona directamente con los microfrontends, definitivamente se puede tener un monolito que esté alineado con un aspecto comercial. Aunque aplicar la arquitectura de microfrontends podría mejorar esta idea al segregar mejor los aspectos comerciales. Y al aplicar DTD estratégico, podemos identificar subdominios, modelarlos en contextos acotados y aplicar el mapeo de contextos para encontrar relaciones entre ellos. Y también decimos que el microfrontend es una implementación técnica del contexto acotado. El mapeo de contextos puede ayudarnos a identificar los puntos donde los microfrontends deben comunicarse. Y una regla importante es que la comunicación entre microfrontends debe mantenerlos aislados entre sí. Ese es el resumen de la charla. Espero haberles dado algo de inspiración sobre cómo aplicar DDD en los problemas que encontramos en el frontend y cómo facilitar la comunicación entre microfrontends de una manera que les ayude a alcanzar objetivos como la autonomía de los equipos. Muchas 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.
Remix Conf Europe 2022Remix Conf Europe 2022
23 min
Scaling Up with Remix and Micro Frontends
Top Content
Do you have a large product built by many teams? Are you struggling to release often? Did your frontend turn into a massive unmaintainable monolith? If, like me, you’ve answered yes to any of those questions, this talk is for you! I’ll show you exactly how you can build a micro frontend architecture with Remix to solve those challenges.
React Advanced Conference 2022React Advanced Conference 2022
30 min
Using useEffect Effectively
Top Content
Can useEffect affect your codebase negatively? From fetching data to fighting with imperative APIs, side effects are one of the biggest sources of frustration in web app development. And let’s be honest, putting everything in useEffect hooks doesn’t help much. In this talk, we'll demystify the useEffect hook and get a better understanding of when (and when not) to use it, as well as discover how declarative effects can make effect management more maintainable in even the most complex React apps.
React Advanced Conference 2021React Advanced Conference 2021
47 min
Design Systems: Walking the Line Between Flexibility and Consistency
Top Content
Design systems aim to bring consistency to a brand's design and make the UI development productive. Component libraries with well-thought API can make this a breeze. But, sometimes an API choice can accidentally overstep and slow the team down! There's a balance there... somewhere. Let's explore some of the problems and possible creative solutions.
React Summit 2023React Summit 2023
23 min
React Concurrency, Explained
React 18! Concurrent features! You might’ve already tried the new APIs like useTransition, or you might’ve just heard of them. But do you know how React 18 achieves the performance wins it brings with itself? In this talk, let’s peek under the hood of React 18’s performance features: - How React 18 lowers the time your page stays frozen (aka TBT) - What exactly happens in the main thread when you run useTransition() - What’s the catch with the improvements (there’s no free cake!), and why Vue.js and Preact straight refused to ship anything similar
Remix Conf Europe 2022Remix Conf Europe 2022
37 min
Full Stack Components
Top Content
Remix is a web framework that gives you the simple mental model of a Multi-Page App (MPA) but the power and capabilities of a Single-Page App (SPA). One of the big challenges of SPAs is network management resulting in a great deal of indirection and buggy code. This is especially noticeable in application state which Remix completely eliminates, but it's also an issue in individual components that communicate with a single-purpose backend endpoint (like a combobox search for example).
In this talk, Kent will demonstrate how Remix enables you to build complex UI components that are connected to a backend in the simplest and most powerful way you've ever seen. Leaving you time to chill with your family or whatever else you do for fun.

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 Summit Remote Edition 2021React Summit Remote Edition 2021
177 min
React Hooks Tips Only the Pros Know
Top Content
Featured Workshop
The addition of the hooks API to React was quite a major change. Before hooks most components had to be class based. Now, with hooks, these are often much simpler functional components. Hooks can be really simple to use. Almost deceptively simple. Because there are still plenty of ways you can mess up with hooks. And it often turns out there are many ways where you can improve your components a better understanding of how each React hook can be used.You will learn all about the pros and cons of the various hooks. You will learn when to use useState() versus useReducer(). We will look at using useContext() efficiently. You will see when to use useLayoutEffect() and when useEffect() is better.
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 Summit 2023React Summit 2023
151 min
Designing Effective Tests With React Testing Library
Featured Workshop
React Testing Library is a great framework for React component tests because there are a lot of questions it answers for you, so you don’t need to worry about those questions. But that doesn’t mean testing is easy. There are still a lot of questions you have to figure out for yourself: How many component tests should you write vs end-to-end tests or lower-level unit tests? How can you test a certain line of code that is tricky to test? And what in the world are you supposed to do about that persistent act() warning?
In this three-hour workshop we’ll introduce React Testing Library along with a mental model for how to think about designing your component tests. This mental model will help you see how to test each bit of logic, whether or not to mock dependencies, and will help improve the design of your components. You’ll walk away with the tools, techniques, and principles you need to implement low-cost, high-value component tests.
Table of contents- The different kinds of React application tests, and where component tests fit in- A mental model for thinking about the inputs and outputs of the components you test- Options for selecting DOM elements to verify and interact with them- The value of mocks and why they shouldn’t be avoided- The challenges with asynchrony in RTL tests and how to handle them
Prerequisites- Familiarity with building applications with React- Basic experience writing automated tests with Jest or another unit testing framework- You do not need any experience with React Testing Library- Machine setup: Node LTS, Yarn
DevOps.js Conf 2024DevOps.js Conf 2024
163 min
AI on Demand: Serverless AI
Featured WorkshopFree
In this workshop, we discuss the merits of serverless architecture and how it can be applied to the AI space. We'll explore options around building serverless RAG applications for a more lambda-esque approach to AI. Next, we'll get hands on and build a sample CRUD app that allows you to store information and query it using an LLM with Workers AI, Vectorize, D1, and Cloudflare Workers.
React Day Berlin 2022React Day Berlin 2022
53 min
Next.js 13: Data Fetching Strategies
Top Content
WorkshopFree
- Introduction- Prerequisites for the workshop- Fetching strategies: fundamentals- Fetching strategies – hands-on: fetch API, cache (static VS dynamic), revalidate, suspense (parallel data fetching)- Test your build and serve it on Vercel- Future: Server components VS Client components- Workshop easter egg (unrelated to the topic, calling out accessibility)- Wrapping up