Arquitectura de código de próxima generación para construir aplicaciones de Node mantenibles

Rate this content
Bookmark

En el panorama actual de desarrollo de software rápido, es esencial contar con herramientas que nos permitan construir, probar y desplegar nuestras aplicaciones de manera rápida y eficiente. Poder enviar características rápidamente implica tener una base de código saludable y mantenible, lo cual puede ser complicado y desafiante, especialmente a largo plazo.

En esta charla, exploraremos estrategias para construir backends de Node mantenibles aprovechando las herramientas que proporciona Nx. Esto incluye cómo modularizar una base de código, utilizar generadores de código para mantener la consistencia, establecer límites de código y cómo mantener la integración continua rápida a medida que crece la base de código.


30 min
14 Apr, 2023

Comments

Sign in or register to post your comment.

Video Summary and Transcription

La charla de hoy se centró en la arquitectura de código, la modularización y la escalabilidad en el desarrollo de software. El orador discutió los beneficios de separar el código por dominio y utilizar herramientas como NX para mejorar la productividad y aplicar una arquitectura modular. También destacaron la importancia de automatizar la creación y configuración de bibliotecas. Además, la charla cubrió estrategias de escalado y despliegue de código, incluyendo el almacenamiento en caché y las migraciones automáticas de código. El orador enfatizó la flexibilidad y escalabilidad de Fastify y las ventajas de utilizar un monorepo para el desarrollo de front-end y back-end.

Available in English

1. Arquitectura de código y escalado

Short description:

Hoy discutiremos la arquitectura de código y la construcción de aplicaciones de nodo mantenibles desde una perspectiva de herramientas. A menudo vemos un problema con características dispersas en diferentes carpetas, lo cual dificulta la escalabilidad y causa conflictos de fusión. Un enfoque mejor es la separación por dominio, que permite características atómicas y localizadas. También exploraremos módulos de dominio, automatización y escalado de código a medida que el producto crece.

¡Así que vamos directo al grano! En realidad, es un título bastante largo, pero lo que quiero analizar un poco hoy es la arquitectura de código y la construcción de aplicaciones de nodo mantenibles, pero desde una perspectiva de herramientas.

La razón principal es que, independientemente de los proyectos de front-end o back-end, que he visto como parte de mi consultoría, como parte de trabajar con algunos de los clientes, a menudo veo una estructura como esta, que está perfectamente bien cuando se inicia un nuevo proyecto, pero el principal problema aquí que se ve es que si estoy hablando de agregar características a los productos, las tengo dispersas en esas diferentes carpetas basadas en la estructura que tengo aquí.

Y la cosa es que esto es una separación por tipo. Entonces tenemos todas las API que son REST o lo que estemos usando, tal vez TRPC, están en esa capa de API mientras que los servicios están en la capa de servicios y el acceso a datos en la capa de acceso a datos. Y el proyecto realmente no escala. A medida que agregas más características, no tendrás solo un archivo, como en este caso muy, muy simple aquí, un ejemplo, sino también si agregas nuevos miembros al equipo, pueden trabajar constantemente en estas carpetas, y es muy fácil que tengan problemas como conflictos de fusión, cosas así. Así que hay una alternativa para eso, que es la separación por dominio. Estoy bastante seguro de que has visto esto. Mucha gente realmente lo hace. Creo que ese es un enfoque mejor allí, simplemente porque ahora puedes ordenar las diferentes características en sus propias áreas para que sean más atómicas, más localizadas en una sola área de todo tu producto. Y nuevamente, obtienes los beneficios de eso. Y estas son las cosas de las que quiero hablar un poco hoy. Así que hablando un poco sobre módulos de dominio, cómo podemos estructurarlo, cómo podemos agregar automatización para ayudarnos con eso y asegurarnos de mantenernos dentro de esos módulos de dominio. Y luego también un poco sobre el escalado de código en el sentido de qué sucede si agrego más de estos y sigo agregando, tal vez agregar un Monorepo, cosas así. Entonces, ¿cómo puedo asegurarme de que mi código escala a medida que mi producto crece?

2. Introducción a NX y Arquitectura Modular

Short description:

Actualmente soy el director senior de experiencia de desarrollo para NX, experto en desarrollo de Google e instructor de IA. NX es de código abierto y ayuda a mejorar la productividad del desarrollador. Se puede utilizar tanto en Monorepo como en configuraciones de proyectos individuales. La modularización por límites de dominio mejora la mantenibilidad, flexibilidad, reutilización y testabilidad. Sin embargo, aún puede ocurrir la importación de módulos de diferentes dominios por accidente. NX aborda este problema proporcionando límites de seguridad y una arquitectura modular. La capa base de NX incluye el espacio de trabajo, mientras que los complementos ofrecen herramientas de automatización específicas de la tecnología. También se introdujo un producto independiente para reutilizar la estructura de NX.

¿más grande? Como se mencionó, mi nombre es Juris Strumflauner. Actualmente soy el director senior de experiencia de desarrollo para NX, experto en desarrollo de Google e instructor de IA. NX es de código abierto, y es una herramienta que ayuda a mejorar la productividad del desarrollador. Hay un conjunto de herramientas y técnicas que se pueden adoptar de forma incremental, como en el nivel inferior, y luego agregar más cosas encima de eso. Somos conocidos por los Monorepos, pero hoy en realidad estoy hablando más sobre el lado del producto independiente. Por lo tanto, no solo se puede utilizar NX en un Monorepo, sino que también es útil para proyectos individuales. ¿Por qué modularizar por límites de dominio? Hoy en día, casi necesitas preguntarle a chatGPD para asegurarte de que estás en el camino correcto, pero en realidad encontré algunas buenas respuestas allí. Y especialmente, obviamente, la parte de mantenibilidad, ¿verdad? Porque como mencionamos antes, tienes esas características pequeñas, más cohesivas, esos módulos están encapsulados de manera ordenada. La flexibilidad, porque puedes eliminar un módulo potencialmente, porque está fuera de lo consistente, no siempre es tan fácil, y la reutilización. A medida que divides, puedes ver patrones de cosas que se reutilizan y que son similares en diferentes dominios. Por lo tanto, puedes extraer aún más y realmente reutilizarlos en tu código. La testabilidad también es un buen efecto secundario. Y hay más de estos tipos de cosas, porque ahora que tienes módulos, puedes probar ese elemento individual de manera aislada también.

Entonces, ¿qué me impide hacer algo como esto, verdad? Porque ahora tengo mi estructura agradable estructurada por módulos, un enfoque de desarrollo orientado al dominio. Pero nada realmente me impide importar, digamos, aquí mi servicio de pedidos importa algo de la API de la lista de productos porque alguien tiene una función en su archivo de nodo y su API de nodo, y lo estoy importando. Incluso puede que no sea intencional, solo mi autocompletado de ideas y trae esa función de utilidad. ¿Podemos hacerlo mejor? ¿Podemos tener algo en su lugar para restringir eso un poco más? Y aquí es donde comenzamos a pensar en NX bastante. Porque, como se mencionó en la introducción, en realidad hicimos consultoría para empresas bastante grandes, que suelen tener una gran base de código. Se encuentran con este tipo de problemas continuamente. Porque tienen de 60 a 300 desarrolladores en esa misma base de código y siguen agregando características todo el día, ¿verdad? Por lo tanto, desea tener algunas limitaciones en su lugar. Ahora, como se mencionó, NX es conocido por el tipo de monorepo. Pero si observas la arquitectura de NX, en realidad es modular en sí mismo. Entonces, en la capa base, puedes ver en la parte superior, está tu espacio de trabajo. Eso puede usar directamente la capa base de NX, lo que significa que obtienes la ejecución de tareas, obtienes un almacenamiento en caché, que es útil para monorepos. Pero luego, opcionalmente, también puedes tener estos complementos. Y los complementos son, puedes imaginarlos como herramientas específicas de tecnología que facilitan tu vida. Pueden generar código, pueden abstraer parte de la configuración de compilación de nivel inferior, proporcionar migraciones de código, todas esas cosas. Y estos complementos específicamente son muy interesantes también en una configuración de producto individual. Esta generación de código no tiene que ver realmente con monorepos. Es solo una herramienta ergonómica que puedes usar para facilitarte la vida. Por lo tanto, se introdujo un producto independiente hace unos meses, casi medio año atrás, donde simplemente reutilizas cómo

3. Producto Independiente y Modularización

Short description:

Se introdujo un producto independiente para reutilizar la estructura de NX. Genera una aplicación Node única con Fastify, Express o Coa. La extracción de la lógica en bibliotecas locales separadas proporciona encapsulación y modularidad. La aplicación importa y registra las bibliotecas, lo que la hace más liviana. Nx proporciona mapeo de rutas para importaciones más limpias. Las partes extraídas se integran en la aplicación, que sirve como contenedor de empaquetado para el despliegue. Es posible una mayor modularización de los módulos locales.

Hace un par de meses, casi medio año atrás, se introdujo un producto independiente para reutilizar la estructura de NX. Por lo general, no nos gustan las carpetas de aplicaciones y bibliotecas, pero para un producto independiente, tienes una carpeta de origen en la raíz. Y hay un generador para eso, donde puedes agregar, por ejemplo, para Node, un conjunto predefinido de Node independiente y no generaría la configuración normal de Node para monorepos, sino que generaría solo una aplicación Node única con Fastify, Express o Coa. Tenemos un par de plantillas que simplemente te facilitan el inicio. Y la estructura se ve así. Entonces, puedes ver aquí que hay una carpeta de origen, hay una aplicación aquí, a la que ya le he agregado algunas características que son, nuevamente, por dominio. Entonces tenemos los pedidos, tenemos los detalles del producto, la lista de productos, cosas así. Y un enfoque obvio que ya tienes en un monorepo, tienes una aplicación y varias bibliotecas, pero puedes tomar ese mismo enfoque para modularizar también tu aplicación independiente, ¿verdad? Por lo tanto, podemos seguir adelante y, en lugar de tener solo ese código monolítico donde tienes solo carpetas, puedes extraerlos y crear bibliotecas locales separadas. Ahora las llamo bibliotecas locales porque no las vamos a publicar, ¿verdad? Pero tienen su propia configuración, su propio proceso de compilación, sus propias pruebas. Y así puedes extraer esa lógica en partes más modulares allí. ¿Cuál es la ventaja? Bueno, en primer lugar, estas están más encapsuladas porque cada una de estas bibliotecas, por ejemplo, viene con un archivo index.js, que es tu punto de entrada público, si quieres, tu API pública hacia el mundo exterior dentro de ese proyecto único. Aquí, por ejemplo, estoy exponiendo las rutas para esa biblioteca, por lo que esta es mi biblioteca de pedidos, por ejemplo, y luego puedo tener más facilidades internamente. Tal vez tenga una función dedicada para cada manejo de ruta y así sucesivamente, como aquí puedes agregar básicamente lo que necesites en tu proyecto. Pero ya puedes ver cómo esto está modularizado. Ahora esta es una aplicación Fastify, eso es solo porque Fastify tiene, en realidad, uso este ejemplo porque Fastify tiene algunos mecanismos incorporados que funcionan muy bien con la modularización. Y Matteo Collina en realidad tiene una charla más profunda sobre Fastify hoy, creo que es una de las últimas charlas, así que definitivamente deberías ver eso, donde él profundizará más en Fastify y por qué ya tiene esa modularidad incorporada. Pero puedes usarlo con Express, como se mencionó, con COA y todos los demás frameworks de Node también. Y luego, en el nivel superior, en este caso Fastify, todo lo que haces es simplemente importar esa biblioteca, ¿verdad? Entonces puedes ver que esto tiene un alcance de NPM y luego registrarlo con Fastify. Ahora probablemente haya una mejor manera de hacerlo, no soy un experto en Fastify, así que tal vez Matteo revele alguna mejor manera de cargarlo dinámicamente, por ejemplo, Fastify tiene propiedades de carga automática. Pero es la forma en que lo conectas. Entonces, la aplicación en realidad se vuelve muy liviana. Ahora puedes preguntarte por qué o cómo puedo importar eso en mi aplicación de nodo, slash, módulos y así sucesivamente. La razón es porque en Nx, por ejemplo, cuando creas una biblioteca de este tipo, ya proporcionamos tipos de mapeo de ruta, por lo que la importación es mucho más agradable, no tienes importaciones relativas extrañas a alguna ubicación dentro de tu proyecto. Esto es solo, nuevamente, por la ergonomía del desarrollador. Entonces, lo que obtenemos es una estructura casi como esta, donde la aplicación de nodo es nuestra aplicación, y las partes que extraemos se vuelven casi independientes. No podemos ejecutarlos solos, pero están integrados en la aplicación, que los agrupa. Por lo tanto, tu aplicación realmente se convierte en el contenedor de empaquetado, la parte de despliegue, porque al final, cuando implementas la aplicación, eso es lo que construiste, se incluirá y compilará los módulos, y luego los enviarás a algún lugar en tu servidor. Pero podemos ir más allá y modularizar esas bibliotecas locales

4. Estructura de Código y Cumplimiento

Short description:

Este es un ejemplo de cómo puedes estructurar tu código dividiéndolo en API, acceso a datos y servicios. Sin embargo, actualmente no hay un mecanismo para hacer cumplir las reglas de importación desde otras bibliotecas. Es posible que deseemos tener un flujo más simplificado desde la API hacia los servicios o el acceso a datos.

modules aún más. Y esto es solo un ejemplo, por lo que puedes estructurarlos como desees. Como uso la misma estructura de capa de servicio de API data aquí, solo por simplicidad. Pero podría ser una forma potencial de cómo dividir y estructurar las cosas. Y a nivel de código, se ve así, donde tienes la API, tienes el acceso a data y tienes los servicios. Entonces, son solo forms respectivos donde cada uno de estos es como su propia biblioteca, y simplemente se encuentra debajo de la carpeta de pedidos. Eso se convierte en mi límite de dominio. Pero aún así, si te das cuenta, todavía no tenemos un mecanismo aquí para hacer cumplir estas reglas, ¿verdad? Ahora tenemos una API más clara. Tenemos un archivo TS indexado público de cada una de estas bibliotecas. Por lo tanto, es más sólido que simplemente tener carpetas, pero aún no hay un mecanismo que no permita importar directamente desde algunas de estas otras bibliotecas, ¿verdad? Puedo acceder directamente. Y por ejemplo, tal vez dentro de la biblioteca de pedidos data acceso, simplemente acceder a alguna función de la API, lo cual potencialmente no queremos, ¿verdad? Es posible que deseemos tener un flujo más simplificado desde la API a través de los servicios.

5. Gestión de Dependencias con Reglas y Automatización de Nx

Short description:

Para manejar diferentes áreas de dominio que acceden a características de otra área de dominio, Nx define reglas en dos dimensiones: tipo y alcance. Los tipos incluyen API, servicio y acceso a datos, mientras que los alcances abarcan pedidos, gestión de perfiles y pago de productos. Etiquetar tipos y definir reglas permite tener dependencias controladas entre dominios. La automatización a través del linting asegura que estas reglas se apliquen automáticamente, evitando comprobaciones manuales durante las solicitudes de extracción. El linting también ofrece extensiones para varios editores, como VS Code.

o desde el acceso a datos de la API. Y de manera diferente, ¿qué sucede si un área de dominio diferente accede a características de otra área de dominio? Algo así es perfectamente legítimo, ¿verdad? El proceso simplemente, debe ser consciente de que permito conscientemente tal importación. Y para manejar esas situaciones, lo que hicimos en Nx es definir reglas, ¿verdad? Y generalmente vienen en dos dimensiones. En primer lugar, está la dimensión del tipo. La dimensión del tipo es básicamente qué tipo de proyecto soy y qué tipo de proyecto puede depender de qué otro tipo de proyecto. Y la segunda dimensión se refiere más al alcance o área de dominio. Entonces, ¿qué alcance puede depender de qué otro alcance? Puede haber algunos que puedan compartir cosas y otros que no puedan compartir cosas. Y así, el tipo en nuestro caso, en este ejemplo simple, pero realmente depende de la estructura de su proyecto, en realidad. Aquí podrían ser API, servicio y acceso adata. Esos son diferentes tipos. Y el alcance son simplemente pedidos, gestión de perfiles, pago de productos. Y generalmente también tienes algunos tipos compartidos, que son entidades, tal vez solo funciones de utilidad. Cosas así.

Ahora, para agregar esos tipos, debes etiquetarlos. Y es por eso que agregamos al proyecto una configuración donde puedes especificar una cadena. Esto puede ser una cadena arbitraria, ¿verdad? Por lo general, los especifico con dos puntos en términos de tipo, y luego el nombre o el valor como alcance y valor real. Pero esto es completamente libre. Puedes inventar tu propia notación si quieres. Y una vez que hayas etiquetado esos, puedes definir estas reglas. Entonces puedes decir, bueno, hay un tipo de API, que puede depender de servicios, de utilidades, de entidades. Incluso puede depender del acceso adata, dependiendo de cómo quieras hacerlo. Y luego está el tipo de alcance, donde puedes decir que este tipo de dominio puede acceder a este otro tipo de dominio. Y podrías ir potencialmente a profundidades arbitrarias, dependiendo de qué tan complejo quieras ir y qué tan estricto quieras ser en esto. Y luego viene laautomation.

Esta es una parte crucial aquí, porque obviamente no quieres verificar eso manualmente en cada PR, sino que quieres tenerlo automatizado. Y el Linting es en realidad un buen candidato para eso, porque es un análisis de código estático. Entonces, miras las reglas que tienes, miras el texto que tienes asociado, sabes qué archivo importa qué otro archivo, en qué productos residen, porque tienes esa información. Así que todo se trata de conectar esas cosas y hacer cumplirlas a través de una regla de lint personalizada, que realmente hemos escrito e integrado en X para asegurarnos de que se ejecuten. Y la parte genial, obviamente, es que el Linting tiene muchas extensiones para varios editores.

6. Automatización de Creación y Configuración de Bibliotecas

Short description:

Puedes utilizar complementos y generadores para automatizar el proceso de creación de bibliotecas y configuración. Esto facilita todo el proceso y evita el copiado y pegado manual. Los generadores te permiten configurar una biblioteca completa con pruebas y configuración, asegurándote de que haga referencia a las definiciones necesarias. También puedes crear tus propios complementos y usarlos localmente para automatizar tareas. Estos complementos se pueden utilizar para modificar proyectos existentes o crear nuevos archivos, como archivos Docker y configuraciones JSON del proyecto.

Este es un ejemplo para VS Code, por ejemplo. Así que tienes esa información lista cuando escribes el código, ya ves de inmediato que esto puede ser importado desde otra parte, porque las reglas no coinciden, no lo permiten. Y obviamente, es algo que puedes ejecutar en la línea de comandos de tu pipeline de CI, ¿verdad? Así que te aseguras incluso ahí de que las cosas que se incluyen en la rama principal sean consistentes. Genial, así que ahora podrías pensar que esto es bueno, ¿verdad? Pero requiere mucho esfuerzo. Necesitas crear esas bibliotecas, asociar etiquetas, idear esas reglas. Bueno, las reglas, probablemente solo necesitas pensarlas una vez y luego tal vez sea cuestión de tiempo, pero aún así es un poco ceremonioso en cierto sentido.

Y aquí es donde entra en juego otra característica de esos complementos, que son especialmente esos generadores. Están diseñados específicamente para hacer que ese proceso sea un poco más ligero y más fácil de abordar, ya que te permiten crear la estructura básica de algunas cosas. Por ejemplo, todas estas bibliotecas que hemos visto son simplemente el resultado de ejecutar este comando para generarlas automáticamente. Por lo general, tienes aquí un concepto en el que está el complemento, luego el generador que invocas y luego los parámetros que le das a ese generador. Y esto obviamente depende del generador que estés ejecutando, pero al ejecutar este comando te permite configurar toda una parte de esta biblioteca con su configuración de testing y tipos de configuración, asegurándote de que haga referencia a las definiciones de nivel de espacio de trabajo como mapeos de rutas, todas esas cosas funcionan de inmediato. Esto es obviamente importante porque facilita todo el proceso, ya que de lo contrario, si tuvieras que copiar y pegar y hacerlo manualmente, sería un poco engorroso. Aquí tienes una simulación de cómo sería. Así que también puedes agregar una simulación y ver qué generaría sin tocar el sistema de archivos. Pero te haces una idea, por ejemplo, de ejecutar aquí el generador de bibliotecas en el paquete de nodo. Crearía esa biblioteca de verificación de módulos de API con todo el archivo readme y todas las cosas que tengo ahí. Y curiosamente, también puedes crear los tuyos propios. Desde el equipo principal de NX, enviamos algunos complementos que nosotros mismos usamos, por lo que tiene sentido porque los usamos para nuestros clientes. Los mantenemos. Tenemos más de 80 complementos de la comunidad y esos son solo los publicados. Muchas personas en realidad solo usan esos complementos localmente en su espacio de trabajo para automatizar tareas. No necesariamente quieres publicarlos. Simplemente crea un complemento localmente, listo en ese mismo repositorio para automatizar la generación de bibliotecas. Y lo que suele suceder es que simplemente toma un proyecto de biblioteca de nodo existente, lo ejecuta primero. Básicamente lo envuelve y luego agrega cosas encima, elimina o ajusta según las pautas de la empresa, las pautas del proyecto, etc. Y no solo son bibliotecas. Son independientes de la tecnología en el sentido de que literalmente puedes escribir archivos. Hay plantillas que tienen marcadores de posición. Así que aquí, por ejemplo, algo que agregamos a nuestro propio complemento de nodo es la configuración de Docker, ¿verdad? Así que

7. Escalado y Despliegue de Código

Short description:

Ahora tenemos un objetivo que podemos ejecutar. Hemos hablado de la automatización de módulos de dominio, pero aún falta el escalado del código. Al expandirlo en piezas más pequeñas, logramos una configuración más modular, lo que facilita la asignación y reemplazo de equipos. Podemos probar piezas individuales y desplegar diferentes objetivos con frecuencias variables. NX proporciona características como el almacenamiento en caché, la distribución y las migraciones automáticas de código, asegurando la escalabilidad junto con una estructura de monorepo.

crea un archivo Docker para ti. Ya crea una configuración en el archivo JSON del proyecto. Ahora tenemos un objetivo que podemos ejecutar. Y aquí específicamente, puedes ver en la parte inferior donde dice que cada vez que ejecutas una construcción de Docker, eso depende de la construcción real del proyecto. Así que primero ejecutaremos la construcción, luego lo envolveremos en Docker, tendremos un contenedor de Docker que luego puedes ejecutar y desplegar.

Así que hemos hablado un poco sobre la automatización de módulos de dominio. Pero una pieza que aún falta un poco es el escalado del código. ¿Cómo se ve eso? Bueno, esta es la situación actual que tenemos. Si realmente expandimos esto en piezas más pequeñas, ya obtenemos una configuración más modular. Asignar equipos es más fácil. Tenemos reglas claras, como las reglas de límites que aseguran que no tengamos referencias extrañas entre esos proyectos. Es potencialmente más fácil de reemplazar. Es como la filosofía de los microservicios, donde puedes agregar un nuevo servicio al lado y eliminar el antiguo, porque si están lo suficientemente desacoplados, eso podría ser fácil debido a que tienen una API clara. Y obviamente podemos probar piezas individuales. No es necesario probar todos los proyectos que tenemos en nuestro espacio de trabajo, sino que podemos probar solo la API del producto si solo hemos cambiado eso. Cosas como esa pueden ayudar, pero también pueden ayudar en el sentido de que, en algún momento, necesites no solo en términos de escalado del código, sino también una frecuencia de despliegue diferente. Tal vez tengas un proyecto en esa área local o un producto que necesite escalar más o necesite desplegarse con más frecuencia. Ese podría ser un punto en el que también cambies a un monorepo. Donde digas, bueno, no solo tenemos una aplicación de nodo, sino que agregamos otra aplicación que simplemente importa algunos de estos módulos que tienen sentido. Y ahora tenemos dos objetivos de despliegue que podemos desplegar tal vez con diferentes frecuencias, tal vez servicios unitarios que se escalan de manera diferente. Porque tal vez para una parte no necesitamos todo el escalado que se necesita. Pero puedes ver que con esa modernización, esa importación es mucho más fácil. Porque todo lo que hacemos es tener una segunda aplicación. Simplemente importamos nuevamente esos espacios de nombres y eso es casi todo, ¿verdad? Y si hablamos de velocidad, obviamente NX proviene de un escenario de monorepo. Así que se escala perfectamente junto con eso, ¿verdad? Como esas características que he resaltado aquí en ese diagrama arquitectónico general, tiene todas estas características incorporadas, como el almacenamiento en caché, la distribución, el análisis del espacio de trabajo, las migraciones automáticas de código. Todas estas cosas que potencialmente necesitarías si luego escalas realmente, como tener múltiples aplicaciones y cientos de proyectos. Entonces, no te quedas solo en ese punto. Y los llamo capas de velocidad porque puedes agregarlas encima, ¿verdad? Puedes comenzar solo con la paralelización inteligente que NX proporciona, donde ejecutas todos los proyectos en paralelo según sus dependencias y el almacenamiento en caché y otras cosas de distribución encima de eso.

Entonces, ¿cómo se ve esto en la vida real? Creo que tengo un par de minutos, así que realmente solo quiero darte una descripción general de alto nivel de cómo se ve este proyecto.

8. Fastify y Estructura NX

Short description:

Esto es Fastify. NX conoce la estructura basada en las importaciones y la visualiza. Optimiza ejecutando pruebas específicas y respeta el orden de construcción. El almacenamiento en caché acelera las ejecuciones posteriores. La automatización es posible con complementos locales y generadores. Se puede generar un nuevo dominio con una configuración elegida. Gracias por su atención y no dude en hacer preguntas.

Entonces, esto es exactamente una aplicación así. Esto es Fastify. Si entro aquí, puedes ver aquí las importaciones de Fastify. Aquí tengo mis rutas que he importado, y estos son los módulos que he extraído aquí, ¿verdad? Por ejemplo, si miro las órdenes, aquí tengo una API, tiene un index.ts, tiene las rutas aquí, y a partir de ahí, lo estructuro como quiero, ¿verdad? Y nuevamente, esto es solo un ejemplo. Puedo ejecutar mbx.NXGraph para visualizar eso, donde muestra cómo se ve la estructura en términos de los módulos. Entonces, lo que NX hace detrás de escena es que conoce la estructura basada en los tipos que importa. Y esto es básicamente solo una visualización donde puedes hacer clic en estos y ver, ¿por qué existe este enlace? ¿Por qué hay una conexión? Y puedes entenderlo y depurarlo. Pero NX también lo utiliza para acelerar las cosas, ¿verdad? Entonces, si cambias algo aquí en los servicios de pago, solo se ejecutarán las pruebas del servicio de pago API y Nodab y así sucesivamente, ¿verdad? Puedes hacer optimizaciones donde no necesitas ejecutar todo. Y eso proviene del trasfondo de Monorepo en el que se encuentra NX. Y de manera similar, si quiero ejecutar digamos todas las pruebas de estilo y testing de este espacio de trabajo, puedes ver que ahora se ejecutan todas las pruebas para todos los proyectos y modelos que tenemos allí, que también podría ejecutar individualmente, ¿verdad? Si solo trabajo en uno y desarrollo uno, puedo ejecutarlo solo para uno y se ejecuta en paralelo en todos ellos, ¿verdad? Y esto también respeta los posibles órdenes de construcción entre los paquetes, ¿verdad? Si un paquete depende de otro, se construye primero, por lo que también se paraleliza de manera inteligente, de alguna manera. Esto tomó alrededor de 30 segundos ahora, 13 segundos, y luego si los ejecuto nuevamente, sería inmediato porque entonces entra en juego el almacenamiento en caché, ¿verdad? Entonces, si ya he ejecutado algunas pruebas antes, entonces si como parte de alguna otra construcción, vuelvo a ejecutar esas mismas pruebas, no se volverán a ejecutar, ¿verdad? Por lo tanto, se beneficiaría de ese almacenamiento en caché y se omitiría desde allí. Además, puedo automatizar cosas, ¿verdad? Aquí, por ejemplo, tengo un complemento local de generación, que tiene un generador y todo lo que tiene son archivos de plantilla que tienen, por ejemplo, aquí, algunos marcadores de posición y luego puedo ejecutarlo. Ni siquiera tengo que ejecutarlo solo a través de la interfaz de usuario o a través de la CLI. Incluso hemos desarrollado una extensión donde puedo ejecutar mi complemento local aquí, proporcionarle un nombre, digamos nuevo dominio, ¿verdad? Ves directamente la salida de Dry Run a continuación y puedo ejecutarlo y luego generaría un nuevo tipo de dominio aquí con la configuración que ya quiero tener, ¿verdad? Dependiendo obviamente de la configuración que elijas. Así que esta es una especie de descripción general de alto nivel súper rápida. Estoy afuera, así que encuéntrame y podemos profundizar un poco más si tienes más preguntas. De lo contrario, me gustaría agradecerles por su atención. Muchas gracias. ¿Te gustaría tomar asiento conmigo? Tengo algunas preguntas para ti. Solo un recordatorio para todos los que están en la sala y en línea, aún pueden hacer preguntas usando Slido hasta que se acabe el tiempo.

9. Haciendo que los Dominios se Comuniquen

Short description:

Para hacer que dos dominios diferentes se comuniquen entre sí, puedes importar código mediante el mapeo de rutas. La apertura de dominios depende de la estructura del producto. Los servicios pueden comunicarse entre sí, o puedes tener APIs internas dedicadas. Tienes la libertad de definir límites dentro de tu proyecto.

Muchas gracias por la charla. Me pareció muy interesante. Una de las primeras preguntas que tuvimos fue ¿cómo haces que dos dominios diferentes se comuniquen entre sí? Supongo que la pregunta se refiere a las reglas de límites, ¿verdad? Si solo quieres compartir código, puedes importarlo mediante ese tipo de mapeo de rutas que mostré antes. En cuanto a cómo quieres abrir esos dominios, realmente depende de la estructura de tu producto. He visto que algunas personas dicen que los servicios, las capas de servicio, siempre pueden comunicarse entre sí, esa sería la forma más liviana, ¿verdad? Donde dices que la API no puede obtener directamente una capa de servicio de otro dominio, sino que prefiero que pase por mi, si quieres, capa de negocio, ¿verdad? Y así abrirlo de esa manera. O incluso puedes tener APIs internas dedicadas donde tienes, no sé, APIs de servicio internas, algo así, un proyecto dedicado donde vuelves a exportar cosas desde tu propia capa de servicio, ¿verdad? Así que puedes ser tan detallado como quieras allí. Dentro de los límites de tu propio proyecto. Puedes definirlos completamente libremente.

10. Límites de módulo en proyectos Lerner

Short description:

Lerner es una herramienta simple que delega la ejecución de tareas a NX para obtener beneficios de caché. No tiene reglas adicionales de límites de módulo, las cuales son proporcionadas por complementos en NX. Este enfoque permite una capa delgada sobre los monolitos existentes, sin una gran implicación. El paquete NX en sí no proporciona estas reglas, deben agregarse a través de complementos.

La siguiente pregunta es si se pueden utilizar límites de módulo en proyectos Lerner. Lerner no lo tiene en este momento. Entonces, Lerner es básicamente, si recuerdas, el diagrama de NX está en la base, ¿verdad? Lerner solo se encarga de la ejecución de tareas, es lo mismo, en realidad delega muchas cosas a NX en segundo plano para obtener todos los beneficios de caché, pero eso es todo, se mantiene simple a propósito. Lo que tiene además es la publicación, cambios automáticos de versión, conversión semántica, ese tipo de cosas, pero en general se mantiene lo más simple posible. Por lo tanto, no tiene esas reglas adicionales de límites de módulo y cosas así. Los límites de módulo casi exclusivamente provienen de los complementos que NX proporciona en la parte superior, ¿verdad? Pero de alguna manera, discutimos la integración de algunos de esos aspectos directamente en NX, pero por otro lado, queremos mantenerlo lo más simple posible, porque generalmente tenemos dos situaciones en las que las personas dicen: `Oye, ya tengo mi monolito, no quiero tener una gran implicación en nada, solo quiero tener una capa muy delgada encima que acelere las cosas, ¿verdad?` Y para mantener eso lo más pequeño posible, el paquete NX en sí no proporciona ninguna de esas reglas de límites adicionales y cosas así, en cambio, debes agregarlas.

11. Estructura de módulo y rutas anidadas

Short description:

En el caso de las rutas anidadas como slash order, slash ID, slash products, la estructura de un módulo depende de los requisitos específicos. Es posible tener estas rutas anidadas dentro del mismo proyecto y API, o incluso crear un submódulo para manejarlas. A menudo se prefiere el enfoque de comenzar con una estructura más simple y luego extraer según sea necesario. Fastify es un marco flexible que permite delegar fácilmente las rutas a submódulos.

complementos en la parte superior. Gracias. ¿Cómo funcionaría o se estructuraría un módulo en el caso de cosas como rutas anidadas, como slash order, slash ID, slash products? Ahí realmente depende, eso también está relacionado con la charla que Matter va a dar, supongo, no sé exactamente de qué trata su charla, pero él va a profundizar en ese enfoque de modularización, pero potencialmente podrías tener esas rutas anidadas dentro del mismo proyecto en la misma API, potencialmente incluso podrías ir un paso más allá y tener un submódulo nuevamente y luego delegar eso a ese submódulo. Por lo general, yo comienzo con lo simple y luego extraigo, pero no hay limitación en ese sentido. Casi como si la limitación estuviera en lo que Fastify puede hacer por ti, básicamente, y lo que he visto, nuevamente, no soy un experto en Fastify, pero lo que he visto hasta ahora es que es bastante flexible en cierto sentido, puedes delegar fácilmente eso a un submódulo.

12. Monorepo y Monolito Modular

Short description:

Definimos la diferencia entre un monorepo y un monolito modular. Los monorepos son adecuados para la colocación conjunta de front-end y back-end. TRPC se puede utilizar para aprovechar el mecanismo de enrutamiento. La compilación de proyectos de Node TypeScript con múltiples módulos utiliza ESBuilt en segundo plano.

como enrutamiento interno. Genial. Tenemos muchas preguntas y, lamentablemente, no suficiente tiempo para responderlas todas, así que solo un recordatorio, lo haré de nuevo en un momento, hay una sala de preguntas y respuestas cerca de la recepción, para aquellos de ustedes en el lugar y para aquellos de ustedes en línea, vayan a Spatial Chat, hagan clic en Q&A para unirse a ese espacio, porque sé que no podremos responderlas todas, pero haremos nuestro mejor esfuerzo. ¿Cómo defines la diferencia entre un monorepo y un monolito modular como el que mostraste? Exactamente, sí. Nosotros en NX, nuestro equipo, tenemos una página web llamada monorepo.tools donde recopilamos diferentes soluciones de monorepo. Hemos recibido muchas contribuciones de diferentes proveedores de herramientas de monorepo donde enumeramos lo que es un monorepo para nosotros. Por lo general, decimos que es cuando tienes múltiples aplicaciones. Si solo tienes una aplicación, técnicamente podrías considerarlo como un monorepo porque tienes una aplicación y múltiples paquetes, pero con ese proyecto independiente ese es nuestro enfoque de monolito modular. Si quieres, donde tienes un proyecto, ese es el predeterminado. De hecho, si ejecutas NXserve, está sirviendo ese proyecto, no tienes que especificar el nombre y una vez que agregas otro, otra aplicación, como tu contenedor de implementación y sistema de empaquetado, entonces comenzaría a hablar de un monorepo. Pero obviamente la línea es difusa, no hay una regla única. ¿Ves esta arquitectura también para aplicaciones de pila completa? ¿Algo así como TRPC? Sí, sí. Funciona perfectamente bien. Y eso es lo que, quiero decir, el proyecto independiente llegó recientemente, pero hemos tenido soporte para Node durante mucho tiempo porque muchos de nuestros clientes y usuarios de NX tenían un escenario donde tenían React en el front-end y luego un back-end de Node, ¿verdad? Y tenerlos ubicados en el mismo lugar, ya podías compartir tipos. Ahora, cosas como TRPC hacen que eso sea aún más fácil, ¿verdad? Porque tienes el mecanismo de enrutamiento incorporado, por lo que puedes aprovecharlo más. De hecho, tenemos un artículo en el blog. Si vas a dev.to.nx, hay un artículo en el blog sobre cómo usar TRPC en un espacio de trabajo NX, por ejemplo. Y nuevamente, es solo cómo los unirías. ¿Cómo encajarían? Creo que incluso hay un generador local que facilita la configuración de cosas como esa. Pero sí, los monorepos son muy adecuados para tener el front-end y el back-end ubicados en el mismo lugar y compartir cosas entre ellos. Sí, tipos especiales.

Siguiente pregunta. Creo que tenemos tiempo para dos más. ¿Cómo funciona la compilación para proyectos de Node TypeScript con múltiples módulos? ¿Necesitas un empaquetador o solo la compilación de TypeScript es suficiente? Sí, básicamente, aprovechamos ESBuilt en segundo plano. Si miras la configuración del proyecto, habrá un complemento base de ESBuilt que usamos para construir esto a partir de TypeScript. Y obviamente, en Node, no necesitarías el proceso de compilación real. Lo único que hacemos adicionalmente es que cuando tienes esos módulos y con los mapeos de rutas de TypeScript, una vez que los compilas a JavaScript, obviamente no tendrás los mapeos de rutas de TypeScript. Así que hemos creado una capa intermedia donde implementamos un resolutor de nombres de módulos, y eso los mapea. Así que generamos un mapa para esos módulos de manera que aún puedas implementarlos como si fuera una sola aplicación de Node. Está en una carpeta de distribución, y luego los módulos se copiarán allí, precompilados, y simplemente se vincularán a través de ese resolutor de módulos que es tu punto de entrada para una aplicación de Node.

13. Empaquetado y Despliegue

Short description:

Puedes empaquetar tu código en un solo archivo sin necesidad de módulos de Node. Esto te permite desplegar funciones o módulos simples fuera de tu monorepo. El contenedor Docker de Node empaquetado consiste en unos pocos archivos individuales que se pueden desplegar directamente en un proveedor. Existe una opción que habilita este empaquetado en un solo archivo. Gracias por sus preguntas y por favor únase a la sección de preguntas y respuestas del orador para más discusión.

Así es como resolvimos ese problema. Pero no necesitas ningún mecanismo de empaquetado en absoluto. Puedes, como agregamos la opción de empaquetarlo en un solo archivo donde ni siquiera necesitas módulos de Node. Y esa fue principalmente nuestra idea, ¿qué pasa si quieres desplegar funciones serias, cosas así, que son simples, pero aún así tal vez quieras desplegarlas fuera de tu monorepo o estos monolitos modulares, entonces tal vez quieras tener ese contenedor Docker de Node empaquetado, solo un par de archivos individuales que despliegas directamente en algún proveedor, como un proveedor de funciones de borde o algo así. Y así puedes configurarlo. No recuerdo la bandera exacta, pero hay una bandera que se puede habilitar, que está habilitada de forma predeterminada, que puede empaquetarlos en un solo archivo. Eso es posible.

Muchas gracias. Se nos acabó el tiempo para preguntas. Todavía hay algunas preguntas encantadoras que deben ser respondidas, incluyendo una de Felix. Muchas gracias por enviarla. Les animo a todos a dirigirse a la sección de preguntas y respuestas del orador junto a la recepción. Si quieren seguir charlando con Yuri, aquellos de ustedes en línea, una vez más, pueden hacer clic en el chat en el espacio espacial para unirse a ese espacio físico. Y demos un gran aplauso a Yuri por su tiempo. Muchas gracias. 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

Node Congress 2022Node Congress 2022
26 min
It's a Jungle Out There: What's Really Going on Inside Your Node_Modules Folder
Top Content
Do you know what’s really going on in your node_modules folder? Software supply chain attacks have exploded over the past 12 months and they’re only accelerating in 2022 and beyond. We’ll dive into examples of recent supply chain attacks and what concrete steps you can take to protect your team from this emerging threat.
You can check the slides for Feross' talk here.
Node Congress 2022Node Congress 2022
34 min
Out of the Box Node.js Diagnostics
In the early years of Node.js, diagnostics and debugging were considerable pain points. Modern versions of Node have improved considerably in these areas. Features like async stack traces, heap snapshots, and CPU profiling no longer require third party modules or modifications to application source code. This talk explores the various diagnostic features that have recently been built into Node.
You can check the slides for Colin's talk here. 
JSNation 2023JSNation 2023
22 min
ESM Loaders: Enhancing Module Loading in Node.js
Native ESM support for Node.js was a chance for the Node.js project to release official support for enhancing the module loading experience, to enable use cases such as on the fly transpilation, module stubbing, support for loading modules from HTTP, and monitoring.
While CommonJS has support for all this, it was never officially supported and was done by hacking into the Node.js runtime code. ESM has fixed all this. We will look at the architecture of ESM loading in Node.js, and discuss the loader API that supports enhancing it. We will also look into advanced features such as loader chaining and off thread execution.
JSNation Live 2021JSNation Live 2021
19 min
Multithreaded Logging with Pino
Top Content
Almost every developer thinks that adding one more log line would not decrease the performance of their server... until logging becomes the biggest bottleneck for their systems! We created one of the fastest JSON loggers for Node.js: pino. One of our key decisions was to remove all "transport" to another process (or infrastructure): it reduced both CPU and memory consumption, removing any bottleneck from logging. However, this created friction and lowered the developer experience of using Pino and in-process transports is the most asked feature our user.In the upcoming version 7, we will solve this problem and increase throughput at the same time: we are introducing pino.transport() to start a worker thread that you can use to transfer your logs safely to other destinations, without sacrificing neither performance nor the developer experience.

Workshops on related topic

Node Congress 2023Node Congress 2023
109 min
Node.js Masterclass
Top Content
Workshop
Have you ever struggled with designing and structuring your Node.js applications? Building applications that are well organised, testable and extendable is not always easy. It can often turn out to be a lot more complicated than you expect it to be. In this live event Matteo will show you how he builds Node.js applications from scratch. You’ll learn how he approaches application design, and the philosophies that he applies to create modular, maintainable and effective applications.

Level: intermediate
JSNation 2023JSNation 2023
104 min
Build and Deploy a Backend With Fastify & Platformatic
WorkshopFree
Platformatic allows you to rapidly develop GraphQL and REST APIs with minimal effort. The best part is that it also allows you to unleash the full potential of Node.js and Fastify whenever you need to. You can fully customise a Platformatic application by writing your own additional features and plugins. In the workshop, we’ll cover both our Open Source modules and our Cloud offering:- Platformatic OSS (open-source software) — Tools and libraries for rapidly building robust applications with Node.js (https://oss.platformatic.dev/).- Platformatic Cloud (currently in beta) — Our hosting platform that includes features such as preview apps, built-in metrics and integration with your Git flow (https://platformatic.dev/). 
In this workshop you'll learn how to develop APIs with Fastify and deploy them to the Platformatic Cloud.
Node Congress 2023Node Congress 2023
63 min
0 to Auth in an Hour Using NodeJS SDK
WorkshopFree
Passwordless authentication may seem complex, but it is simple to add it to any app using the right tool.
We will enhance a full-stack JS application (Node.JS backend + React frontend) to authenticate users with OAuth (social login) and One Time Passwords (email), including:- User authentication - Managing user interactions, returning session / refresh JWTs- Session management and validation - Storing the session for subsequent client requests, validating / refreshing sessions
At the end of the workshop, we will also touch on another approach to code authentication using frontend Descope Flows (drag-and-drop workflows), while keeping only session validation in the backend. With this, we will also show how easy it is to enable biometrics and other passwordless authentication methods.
Table of contents- A quick intro to core authentication concepts- Coding- Why passwordless matters
Prerequisites- IDE for your choice- Node 18 or higher
JSNation Live 2021JSNation Live 2021
156 min
Building a Hyper Fast Web Server with Deno
WorkshopFree
Deno 1.9 introduced a new web server API that takes advantage of Hyper, a fast and correct HTTP implementation for Rust. Using this API instead of the std/http implementation increases performance and provides support for HTTP2. In this workshop, learn how to create a web server utilizing Hyper under the hood and boost the performance for your web apps.
React Summit 2022React Summit 2022
164 min
GraphQL - From Zero to Hero in 3 hours
Workshop
How to build a fullstack GraphQL application (Postgres + NestJs + React) in the shortest time possible.
All beginnings are hard. Even harder than choosing the technology is often developing a suitable architecture. Especially when it comes to GraphQL.
In this workshop, you will get a variety of best practices that you would normally have to work through over a number of projects - all in just three hours.
If you've always wanted to participate in a hackathon to get something up and running in the shortest amount of time - then take an active part in this workshop, and participate in the thought processes of the trainer.
TestJS Summit 2023TestJS Summit 2023
78 min
Mastering Node.js Test Runner
Workshop
Node.js test runner is modern, fast, and doesn't require additional libraries, but understanding and using it well can be tricky. You will learn how to use Node.js test runner to its full potential. We'll show you how it compares to other tools, how to set it up, and how to run your tests effectively. During the workshop, we'll do exercises to help you get comfortable with filtering, using native assertions, running tests in parallel, using CLI, and more. We'll also talk about working with TypeScript, making custom reports, and code coverage.