Una revisión de cómo estamos utilizando Remix en Daffy.org para cambiar la forma en que las personas donan a organizaciones benéficas.
Hablaremos sobre por qué decidimos usar Remix, cómo lo hemos utilizado y migrado desde nuestra aplicación frontend anterior, y algunos patrones y bibliotecas que hemos desarrollado internamente.
This talk has been presented at Remix Conf Europe 2022, check out the latest edition of this React Conference.
FAQ
Daphne es una plataforma diseñada para ayudar a las personas a donar de manera automatizada a las organizaciones benéficas que les importan, mediante una aplicación iOS y una aplicación web.
Daphne utiliza Remix para desarrollar su aplicación web, facilitando la gestión del frontend y mejorando la resiliencia y simplicidad de las operaciones.
La migración a Remix fue decidida para mejorar la resiliencia de la aplicación, simplificar la validación y manejo de formularios, y resolver problemas de lentitud y errores en la carga de páginas.
Durante la migración, Remix y Next.js se conectaron a un servidor Express común, compartiendo el estado de autenticación y permitiendo una transición suave entre ambas tecnologías.
Remix facilita la refactorización y evita la duplicación de código gracias a su manejo de rutas anidadas y componentes que viven directamente en las rutas, simplificando la estructura del proyecto.
Remix utiliza límites de errores para capturar errores inesperados y mostrar mensajes informativos al usuario, contribuyendo a la resiliencia de la aplicación.
Daphne utilizó Express para ejecutar ambos frameworks en un único proceso, manejando las rutas específicas y compartiendo el estado de autenticación entre Remix y Next.js, manteniendo así la funcionalidad durante la transición.
Remix mejora la experiencia del usuario mediante el mejoramiento progresivo, permitiendo que la aplicación sea parcialmente utilizable incluso sin JavaScript, y optimiza la carga de recursos para una navegación más rápida.
Daphne utiliza Remix para su aplicación web, beneficiándose de su resistencia, límites de errores, límites de caché y mejora progresiva. Remix simplifica el envío de formularios, la autorización y la validación, y permite una refactorización más fácil y evitar la duplicación de código. Next y Remix se utilizan juntos, con Remix sirviendo como el backend para el frontend y manejando la agregación de datos. Remix proporciona funciones de consulta para obtener datos, mutaciones para la validación de datos de formularios y llamadas a API, y convenciones personalizadas utilizando la exportación de manejo. La migración a Remix resultó en archivos JavaScript más pequeños, una navegación más rápida y la capacidad de precargar datos y activos. El proceso de migración tomó alrededor de nueve meses e involucró la mezcla de Next.js y Remix utilizando Express. Contratar a alguien para trabajar en Remix es más fácil que contratar para otros frameworks.
Hola, bienvenidos a mi presentación. Soy Sergio Salambri, desarrollador web en Daphne, y voy a hablar sobre cómo usamos Daphne y Remix en Daphne. Daphne es una plataforma para ayudar a las personas a donar a las organizaciones benéficas en las que se preocupan de manera automatizada. Usamos Remix para nuestra aplicación web porque proporciona resiliencia, límites de errores, límites de caché y mejora progresiva. Con Remix, podemos capturar errores inesperados, mostrar errores conocidos y asegurarnos de que la aplicación siga siendo utilizable incluso si JavaScript no se carga. Además, elegimos RemixBoot por sus capacidades de mutación de formularios.
a hablar sobre cómo usamos Daphne, cómo usamos Remix en Daphne. Entonces, ¿qué es Daphne? Daphne es una plataforma para ayudar a las personas a donar a las organizaciones benéficas en las que se preocupan de manera automatizada. Para hacer eso, proporcionamos tanto una aplicación iOS como una aplicación web y usamos Remix para esa aplicación web. También usamos Remix para otras aplicaciones. Nos vamos a enfocar en cómo lo usamos para la aplicación web principal. Eso es lo que los usuarios utilizan. Así que primero empezamos a usar y construir el front-end. Daphne o MVP era una aplicación de enrutador que se servía desde una ruta de Rails y se compilaba con Rails webpacker. Funcionaba muy bien para las pruebas de concepto del MVP, pero luego lo cambiamos a Next.js para las páginas de aterrizaje y la web porque queríamos tener un servidor y otras características. Tuvimos algunos problemas con la configuración. Las páginas eran lentas en una conexión lenta al sitio web. Si había un error en una de nuestras llamadas a la API para obtener data para renderizar en la página, se bloquearían y mostrarían un error sospechado. Además, los forms eran demasiado complejos para validar y ejecutar errores. Teníamos duplicación innecesaria de código. También el código de fragmentación en la función get server-side props era demasiado complejo, porque necesitas obtenerlo en funciones de alto orden. Así que decidimos que necesitábamos usar algo diferente, y elegimos usar RemixBoot. Y la razón para eso es la primera, la resiliencia. La resiliencia es qué tan bien una aplicación puede seguir funcionando en caso de un error. Remix no hace que tu aplicación funcione todo el tiempo si hay un error, pero te ayuda mucho a llegar allí o cerca de allí. Con límites de errores, podemos capturar cualquier error inesperado y mostrar algo al usuario, como, oye, algo salió mal. Vamos a – ahora sabemos de esto, pero puedes contactar soporte si necesitas más ayuda. Con límites de caché, podemos mostrar cualquier error conocido. Si el usuario va a una organización benéfica y esa organización no existe, no es divertido. O si un proveedor de usuario no existe, no es divertido. Si quieren hacer algo que requiere más dinero en su cuenta, podemos mostrar un mensaje de pago faltante o una interfaz de usuario con límites de caché. También podemos usar Mejora Progresiva. Si JavaScript no se carga por alguna razón, la aplicación sigue siendo en su mayoría utilizable. Al menos pueden acceder al contenido.
2. Simplificando el Envío de Formularios y la Migración a Remix
Short description:
Con Remix, el proceso de envío de formularios, autorización y validación se vuelve mucho más sencillo. La llamada a la acción está en el mismo archivo que el formulario, lo que facilita entender el flujo de la aplicación. Remix también ofrece convenciones y separación de responsabilidades, lo que permite una refactorización más fácil y evitar la duplicación de código. Además, la migración a Remix se realizó ejecutando Remix y Next juntos, utilizando el servidor Express para ejecutar ambas aplicaciones en un solo proceso.
Otra razón fue la mutación de formularios. Con la pila anterior, teníamos que hacer muchas cosas para realizar una mutación, como crear un formulario, un estado para la entrada, serializarlo, enviarlo en un fetch a una API, crear la API en otro archivo, enviar autorización, validar los datos y enviarlos a nuestra API de Rails. Con Remix, esto se vuelve mucho más sencillo. Simplemente renderizamos el formulario, exportamos la acción en el mismo archivo donde vive el formulario. Podemos realizar el servicio y lanzar la autorización y validación de los datos antes de enviarlos a Rails y funciona. Es mucho más sencillo.
La llamada a la acción también está en el mismo archivo del formulario. Eso es un gran beneficio para poder saber qué está sucediendo en una ruta. Vamos a una ruta, entonces hay un formulario. Vamos a la acción. Sabemos qué está haciendo ese formulario. También podemos agregar validación con Solve. Los formularios de múltiples pasos pueden funcionar de manera mucho más sencilla con JavaScript y con el botón de retroceso, algo que no teníamos antes. Y podemos utilizar la transición del usuario para mejorar la experiencia de los usuarios. Y así, desde estados de carga hasta interfaces de usuario optimistas. Las convenciones y la separación de responsabilidades también es otra razón por la que elegimos Remix. Los archivos de rutas ayudan mucho con la refactorización. Podemos simplemente eliminar un archivo de ruta y con eso eliminar la acción, el cargador, el componente, los enlaces, todo. También las rutas anidadas ayudan a evitar la duplicación. No necesitamos mover código a otro archivo e importarlo en muchos archivos como encabezados, a través de las rutas. Simplemente creamos un patrón, una ruta de diseño, y colocamos dentro todo lo que necesita ese encabezado y listo. Y el componente luego vive en la ruta. Los cargadores y las acciones también utilizan estándares. Y pasamos menos tiempo en la documentación de Remix y más tiempo en la documentación de Mozilla Developer Network. También significa que contratar y enseñar la pila es más sencillo. Contratamos a alguien que no conocía Remix y ella aprendió Remix para la entrevista y pasó la entrevista y otros desarrolladores enfocados en el backend pudieron aprender Remix súper rápido, en un día o menos de un día, y comenzaron a usarlo. Ahora, cómo nos migramos a Remix. Sabíamos que queríamos usar Remix, pero aún teníamos esta gran aplicación de Next. Lo que hicimos, lo primero fue que no podíamos migrar todo de una vez, así que decidimos ejecutar Remix y Next juntos. Para hacer esto, aprovechamos que Remix se puede conectar a un servidor Express y Next también se puede conectar a un servidor Express.
3. Usando Next y Remix Juntos
Short description:
Enviamos solicitudes a Next para APIs y activos, pero todo lo demás va a Remix. Manejamos los errores de Next inicialmente, pero eventualmente cambiamos a enviar todas las solicitudes a Remix. Compartimos el estado de autenticación entre aplicaciones usando un sessionStore compartido. Durante la migración, utilizamos navegación de página completa para enlaces y formularios. Ahora, Remix sirve como el backend para nuestro frontend, agregando datos de múltiples puntos finales de API. Los cargadores manejan la obtención, filtrado y transformación de datos, simplificando nuestros componentes de React.
Usamos express para ejecutar ambos procesos, ambas aplicaciones en un solo proceso. Enviamos todo desde /_next/whatever a Next, para que pueda manejar APIs y enviar activos. Usamos express static para la compilación pública, la carpeta pública y la compilación pública de Remix. Enviamos una solicitud específica a Remix y el resto de las solicitudes a Next inicialmente. Esto significa que al principio tuvimos que manejar los errores de Next, pero eventualmente cambiamos y comenzamos a enviar todas las solicitudes a Remix de forma predeterminada y solo las solicitudes específicas a NextJS. Hicimos esto cuando movimos toda nuestra caché, todas las rutas, como el perfil de usuario, a Remix, y eso nos permitió hacer el cambio y decir, ok, a partir de ahora todo va a Remix excepto esta ruta, como la ruta de API de Next o algunas rutas que aún estábamos sirviendo con HTML para Next. También tuvimos que compartir el estado de autenticación porque el cambio de una aplicación a otra para el usuario debería haber sido el mismo. El usuario no sabía si la ruta estaba usando Remix o Next, excepto probablemente porque era más rápido. Así que creamos un mixout. Cambiamos el SDK de Next.js a RemixOut con la estrategia Out0 y luego nos dimos cuenta de que el objeto de almacenamiento de sesión de Remix en realidad no está vinculado de ninguna manera a Remix. Podemos usarlo en Next. Puedes instalar esa parte en la aplicación de Next y hacer que funcione. Así puedes ver cómo puedes pasar el valor de res.headers.cookie a sessionStore.getSession y obtener la sesión, y luego confirmar la sesión y obtener la cadena para enviar a res.setHeader. Y de la misma manera podemos hacerlo con Remix. Así que compartimos este sessionStore para poder compartir el estado de autenticación entre aplicaciones.
Finalmente, otro problema que tuvimos fue que los enlaces de Remix apuntaban a aplicaciones de Next mientras intentábamos hacer una navegación del lado del cliente, y eso fallaba porque la ruta aún no existía en Remix. Y lo mismo sucedía en sentido contrario. Los enlaces de Next que apuntaban a Remix intentaban hacer lo mismo, intentando cargar la siguiente ruta a la que el usuario estaba navegando usando Next, pero eso ya no existía. La solución fue, mientras la migración aún estaba en curso, agregamos reload document en los componentes de Remix y evitamos usar el componente de enlace de Next. Así que cada enlace era una navegación de página completa. Lo mismo con los formularios. Cada formulario causaba una navegación de página completa incluso si el enlace o el formulario apuntaban a una ruta que ya sabíamos que estaba usando Remix. Así que establecimos la línea de base, básicamente todo usaba navegación de página completa, y una vez que la migración estuvo lista y sabíamos que no había más código de Next.js en ejecución en producción, eliminamos todos los documentos de recarga y todos se convirtieron en una aplicación de una sola página.
Ahora cómo usamos Remix en Daffin. Primero, Remix es un backend para frontend para nosotros. El usuario interactúa solo con Remix, no hay forma de que el usuario vea una solicitud a la API de Rails, simplemente la envía a Remix y desde allí a Rails, y usamos esto para agregar datos de múltiples puntos finales de nuestra API. En el lado del servidor, en los cargadores, simplemente podemos obtener múltiples puntos finales. Obtenemos los datos y también los filtramos en el lado del servidor, y podemos transformar los datos. Por ejemplo, convertimos objetos de fecha en mensajes localizados o números en la cantidad de cadena localizada. Y debido a esto, porque la mayoría de estas cosas que solíamos hacer en la interfaz de usuario ahora están en los cargadores, nuestros componentes de React son más simples porque se centran solo en la interfaz de usuario, se centran en obtener los datos de useLoaderData y mostrarlos al usuario, y algunos estados o esfuerzos específicos para la integración principalmente con servicios de terceros.
4. Estructura de archivos raíz y acoplamiento de componentes
Short description:
Tenemos la idea de que un archivo raíz contiene todo lo necesario, evitando el acoplamiento de componentes con datos. Los componentes compartidos reciben datos de las props y encuentran exactamente lo que necesitan. Los componentes complejos están vinculados a la raíz y residen en la propia raíz.
Además, tenemos la idea de que un archivo raíz debe contener todo lo que necesitan, al menos tanto como sea posible. Solo movemos los componentes a la carpeta 'components' de las aplicaciones si son realmente compartidos, es decir, si los usamos en casi todas las raíces o al menos en más de tres. Por lo tanto, sabemos antes de mover un componente a esta carpeta que realmente se va a utilizar en muchas partes y no está vinculado a los datos. Esto permite una refactorización sencilla de las raíces porque si todo está en la raíz, simplemente podemos eliminar la raíz y eliminar todo el código relacionado. No hay forma de que eliminemos una raíz y dejemos el componente en la carpeta 'components' porque no estamos seguros si algo más lo está utilizando. También evitamos el acoplamiento de componentes con los datos. Debido a que todos nuestros componentes compartidos solo reciben datos de las props y no de los datos. Y encontrarán exactamente lo que necesitan. Y muchos componentes simples porque si son componentes complejos, generalmente están vinculados a lo que
5. Funciones de consulta, Mutaciones y Manejo de Errores
Short description:
Tenemos el concepto de funciones de consulta en Remix, que son funciones asíncronas que obtienen datos de la API y manejan el filtrado, análisis y transformación. Estas funciones se colocan al final del código del cargador. Los errores en consultas importantes hacen que la captura principal falle dentro del cargador, mientras que otros fallan silenciosamente. Manejamos las mutaciones de manera similar, validando los datos del formulario con un esquema SOD y enviándolos a la API. Devolvemos respuestas JSON con estados de éxito o error según corresponda. También manejamos errores de interfaz de usuario moviendo partes de la interfaz de usuario a componentes separados y renderizándolos en función de la disponibilidad de datos. Además, definimos convenciones personalizadas utilizando la exportación de manejo y tenemos un cliente de API seguro en cuanto a tipos para garantizar la seguridad de tipos al obtener datos de nuestra propia API.
el root está haciendo específicamente y duerme en el propio root. También tenemos esta idea de una función de consulta. Así es como se ve un cargador en Remix, el código inicial donde autenticamos al usuario, creamos clientes de API, instancias y cosas así se espera que no fallen. Entonces si fallan, queremos que el límite de error se renderice. Luego intentamos capturar todo lo que se espera que pueda fallar. Si hay un error, capturamos la excepción y la enviamos a Sentry. Y también devolvemos o verdadero una respuesta para informar al usuario que algo salió mal. Devolvemos verdadero cuando la palabra root es mala, y devolvemos cuando aún podemos renderizar parte de ella. Y las funciones de consulta son estas funciones para obtener algo, funciones asíncronas que tenemos dentro del cargador al final del código del cargador donde obtenemos data de la API. También lo filtramos o analizamos o transformamos allí para que el código esté en una sola función. Y dentro de esta función, podemos intentar capturar la solicitud. Esto significa que si la obtención de donaciones falla, en este caso, queremos que el root falle porque si estás viendo una donación específica, nada tiene sentido sin esos data. Pero si la obtención de organizaciones benéficas falla, podemos devolver nulo y capturar la excepción para enviarla a Sentry. Entonces sabemos que algo falló, pero para el usuario lo que va a suceder es que la lista de organizaciones benéficas desaparece de la interfaz de usuario. Por lo tanto, las consultas importantes hacen que la captura principal falle dentro del cargador pero las demás fallan silenciosamente. Hacemos algo similar con las mutaciones. Entonces la mutación es nuevamente una función que colocamos en la parte inferior de la acción donde creamos el esquema SOD, validamos los datos del formulario con el esquema SOD y los enviamos a la API. Y si es un éxito, podemos devolver JSON con el estado de éxito o un error rojo o lo que sea necesario. Y si hay un error aleatorio, verificamos si es un error SOD, lo devolvemos en JSON con un estado de error y la lista de mensajes de error. Si no es un error SOD, significa que algo más falló, recibimos su recepción y mostramos un mensaje que generalmente le indica al usuario que se comunique con el soporte técnico que ya conocemos el error. También manejamos errores en la interfaz de usuario de esta manera, por lo que tenemos el límite de caché que en caso de que el cargador falle, el root falla. Pero movemos una parte de la interfaz de usuario de la raíz a diferentes componentes, y dentro de esos componentes que viven en el mismo archivo que la raíz, llamamos a user.data, obtenemos los data que necesitamos y lo renderizamos, y si el data es nulo, simplemente devolvemos nulo para ocultar esa parte de la interfaz. También definimos convenciones personalizadas utilizando la exportación de manejo. La mayoría de estas convenciones personalizadas no forman parte de Remick Utils, cosas como scripts de hidratación y enlaces dinámicos y datos estructurados son parte de Remick Utils, y tenemos este tipo global, Daffy.handle, al que podemos adjuntar nuestra exportación de manejo y definir lo que el root puede establecer allí. Entonces nuestros roots definen si necesitan o no javascript, si necesitan scripts externos, pueden cargarlo de esa manera. También extendemos esta convención para diferentes diseños, por lo que el handle de embarque tiene convenciones diferentes adjuntas a las globales. Lo mismo ocurre con el diseño en el handle de la aplicación y puedes ver, por ejemplo, en el handle de la aplicación tenemos este componente aside que recibe las props del cargador data y esto permite que el diseño de la aplicación renderice la barra lateral con un aside, pero lo renderice en un diseño más grande con las rutas secundarias específicas de la raíz dentro de otro lugar. Por lo tanto, podemos usar esto como una forma de definir espacios o luego venderlo de alguna manera para diferentes partes del diseño. También tenemos un cliente de API seguro en cuanto a tipos para no usar algo como Prisma porque obtenemos una API. Entonces, para tener seguridad de tipos cuando obtenemos datos de nuestra propia API, definimos un esquema con sort, exportamos, inferimos el tipo a partir de ahí y cuando obtenemos la API, simplemente analizamos los datos tal como vienen de sort con sort y dejamos que falle si hay un error. Entonces, si hay un error allí, sabemos que algo cambió en la API que no se esperaba que cambiara y podemos revisar revisamos el error y ver qué sucedió y si no y si algo funcionó correctamente el valor de retorno del método de la API va a tener el tipo correcto con el tipo de donación del esquema.
6. Rutas de Recursos y Bibliotecas de Remix
Short description:
Utilizamos rutas de recursos para generar PDF y imágenes de Open Graph. La biblioteca React PDF se utiliza para renderizar PDF con soporte de localización de Y18-next. Para las imágenes de Open Graph, renderizamos SVG y las transformamos según sea necesario. RemixAdafi ha contribuido a la comunidad de Remix, lo que ha llevado a la creación de RemixUtils, RemixOut y RemixY18next. Estas bibliotecas proporcionan varias características e integraciones. ¡Gracias por acompañarme!
También utilizamos muchas rutas de recursos para diferentes cosas. Por ejemplo, generamos PDF porque tenemos que proporcionar a los usuarios un informe sobre la donación con fines fiscales. Por lo tanto, utilizamos una biblioteca de PDF de React para renderizar un React dentro de una ruta de recurso y generar un PDF. Localizamos el PDF utilizando la biblioteca Y18-next y luego, después de renderizar el PDF, enviamos una respuesta utilizando el ayudante de PDF de RemixUtils y de esta manera podemos generar un PDF dinámico con React. También utilizamos rutas de recursos para imágenes de Open Graph. De la misma manera que obtenemos parámetros de los parámetros de búsqueda de la URL, utilizamos React para renderizar un SVG como una cadena. Si el usuario espera una respuesta SVG, simplemente la devolvemos. Si no, podemos transformar el SVG a otro formato como PNG, JPG, WebP, etc., y guardar el archivo con una cabecera de tipo de contenido. De esta manera, podemos optimizar las imágenes para OpenGraph según sea necesario. RemixAdafi ha contribuido a la comunidad de Remix porque se extrajeron muchas cosas de allí. RemixUtils existe. Gracias a RemixAdafi, utilizamos useHydrated solo en el cliente, useGlobalPendingState y más cosas provienen de funciones y componentes internos. Lo utilizamos en Adafi y luego lo extraemos a RemixUtils. RemixOut nació debido a la necesidad de implementar la autenticación de Auth0. En Dafi, publiqué el primer borrador con mi intención inicial y luego, a partir de la prueba de concepto que tenemos de Remix, creamos la versión 1 de RemixOut con la estrategia de Auth0 que luego se extrajo a otro paquete y la biblioteca creció con la comunidad. RemixY18next también existe gracias a Dafi que utiliza Remix porque necesitamos localizar la aplicación. La aplicación en realidad solo está en inglés pero ya admitimos la localización. Elegimos Y18next traducido por ellos. Mi implementación inicial se publicó como un artículo. Luego extraímos la biblioteca con el código de salida. Lo utilizamos como Y18next a partir de la prueba de concepto de Dafi. Así se creó la biblioteca y la comunidad comenzó a contribuir. Eso es todo. Gracias por acompañarme. Sergio, ¿cómo estás hoy? Estoy bien. Oh, bien. Bueno, esa fue una charla increíble. Muchas gracias. Queremos pasar a Slido.
QnA
Migración de Proyectos Existentes a Remix
Short description:
Preguntamos a la audiencia si han migrado un proyecto existente a Remix. El 53% dijo que no, pero les gustaría hacerlo, mientras que el 38% dijo que sí. Solo el 6% no tiene planes de migrar. Es genial ver que muchas personas están planeando migrar. La característica favorita de Remix mencionada por la audiencia son las mutaciones, que se considera la parte más difícil de cualquier aplicación. El proceso de migración tomó alrededor de nueve meses, comenzando en enero y finalizando en septiembre. La migración se realizó de forma incremental, aprovechando las oportunidades de rediseño y los espacios de trabajo vacíos.
y veamos cuáles fueron los resultados de la encuesta. Permítanme mostrarles mi pantalla. Preguntamos, ¿han migrado un proyecto existente a Remix? Y el 53% de las personas dijo que no, aún no lo han migrado, pero les gustaría hacerlo. Y luego algunas personas dijeron que sí, aproximadamente el 38%. Y luego nadie, no, no tengo planes, alrededor del 6%. Así que muy poca gente no quiere migrar en absoluto. Pero es genial que muchas personas estén planeando hacerlo, ¿verdad? Sí, sí. Deberían, deberían seguir adelante con eso. Esperemos que esta charla les haya ayudado a motivarse y comenzar a migrar sus aplicaciones. Y no olviden que siempre pueden unirse a nosotros en slido.com y el código es 1-818 si quieren responder a alguna de estas encuestas que estamos haciendo. Muy bien, volvamos a las preguntas y respuestas. Tenemos una pregunta que hicimos a la audiencia al principio y ahora le preguntamos a cada orador, nos gustaría saber cuál es su característica favorita de Remix. Creo que es la misma. La mayoría son las mutaciones. Sí. Es la parte más difícil en cualquier aplicación. Es fácil leer data. Es difícil mutarlo correctamente y volver a validar. Y todas las cosas que Remix hace en torno a eso, es súper fácil con acciones y forms. Sí, creo que podríamos profundizar en eso en una pregunta más adelante. Pero esa es una respuesta muy popular a esa pregunta, las mutaciones. Escuchamos mucho sobre los cargadores y las acciones. Y creo que esa es una característica muy popular y solicitada también. Entonces, ¿cuánto tiempo te llevó realmente hacer la migración de la que hablaste? Comenzamos en enero de este año. Y si no me equivoco en mi memoria, lo completamos en septiembre. Así que fueron alrededor de nueve meses para hacer la migración mientras seguimos agregando más características. De acuerdo. ¿Cómo fue ese proceso para ti, entonces, tomando ese tiempo? ¿Pudiste cambiar e migrar tu aplicación de forma incremental? Sí. Bueno, hacemos eso. Como somos una pequeña startup, todavía estamos descubriendo muchas cosas en nuestro producto. Entonces, cuando rediseñamos cosas para mejorar cómo funcionan, aprovechamos esa oportunidad para moverlas a Remix y construir una nueva versión, el Rendering Remix. Y luego cuando teníamos algunos espacios vacíos de trabajo, no teníamos nada más que hacer durante unos días, aprovechábamos ese tiempo para migrar otras cosas que no eran tan importantes y que no tocábamos tanto, pero que teníamos en NextJS, así que las migrábamos a Remix.
Mezclando Next.js y Remix
Short description:
Para mezclar Next.js y Remix juntos, utilizamos Express para ejecutar ambas aplicaciones en el mismo servidor. Compartimos el estado de autenticación y aprovechamos los patrones de interfaz de Remix. En lugar de realizar una carga pesada de datos en el lado del cliente, utilizamos GetServerSideProps y realizamos una transición fácil al Loader de Remix. La lógica del código se mantuvo igual, con solo ajustes menores en la lectura de solicitudes y el envío de respuestas.
¿Cuáles son algunos de los procesos que utilizaste para realizar esos cambios incrementales? Porque te moviste de Next.js a Remix, que tienen dos APIs muy diferentes. ¿Cómo lograste mezclarlos? Bueno, lo que hicimos fue utilizar Express para ejecutar ambas aplicaciones en el mismo servidor utilizando un solo proceso, y luego tuvimos que compartir el estado de autenticación después de descubrir que mover las cosas básicamente revelaba todo desde cero en Remix, tal vez reutilizando parte de la interfaz de usuario. Afortunadamente para nosotros, porque realmente me gustan muchos de los patrones de Remix, no hicimos demasiadas cosas en el lado del cliente, como la obtención de datos, así que utilizamos GetServerSideProps. Mover de GetServerSideProps a Loader no es tan difícil como si hubiéramos utilizado otra biblioteca para consultar datos en el lado del cliente. De hecho, es interesante que casi podrías buscar y reemplazar tus GetServerSideProps con Loader y obtener los datos que necesitas para tu ruta. Me gusta eso. Sí, gran parte del código es el mismo. Solo necesitas cambiar cómo leer las cosas de la solicitud y cómo enviar las cosas en la respuesta. Pero el resto del código, la lógica real que utilizas allí, es la misma. Genial. Supongo que eso lo haría un poco más fácil.
Beneficios de migrar a Remix
Short description:
La migración a Remix ha resultado en archivos JavaScript más pequeños, una navegación más rápida y la capacidad de precargar datos y activos. El enrutador de Remix permite la carga incremental de componentes necesarios. El mejoramiento progresivo en Remix garantiza que la aplicación funcione sin JavaScript y la mejora para los usuarios con JavaScript. Esto es particularmente importante para nuestra aplicación financiera. Utilizamos enlaces y formularios en Remix para mantener la funcionalidad incluso sin JavaScript. Convencer a nuestro equipo de migrar a Remix fue un proceso que comenzó cuando nos dimos cuenta de la necesidad de una solución mejor que los enrutadores de React configurados por Rails.
Entonces, ¿cuáles son algunos de los beneficios que has visto al migrar de React o de Remix en tu aplicación? Tenemos archivos JavaScript mucho más pequeños en el cliente. Por lo tanto, nuestra aplicación se siente más rápida cuando navegas con esta función de precarga de enlaces. Remix puede precargar no solo el código, sino también los datos y otros activos. Entonces, si tenemos imágenes que hemos precargado, puede obtenerlas, y si tenemos un cargador en la siguiente ruta, también podemos comenzar a precargar antes de que el usuario realmente haga clic en un enlace y navegar más rápido a la otra página, incluso si estamos haciendo representación en el servidor todo el tiempo.
Sí. Entonces, tal vez tenga que ver con la forma en que el enrutador de Remix está configurado y es capaz de cargar incrementalmente algunas de esas cosas que necesitas. Sí. Sí, genial. Bien, al hacer el cambio de Next.js a Remix, mencionaste que el mejoramiento progresivo también es una de las razones. ¿Puedes explicar más sobre eso y cómo Remix maneja el mejoramiento progresivo? Sí. Para aquellos que no lo saben, el mejoramiento progresivo es esta idea de que tu aplicación funciona sin JavaScript y luego lo mejoras para que funcione mejor para las personas con JavaScript, que suele ser la mayoría de los usuarios. En nuestro caso, trabajamos con dinero y si la aplicación no funciona, es preocupante para los usuarios, ¿verdad? Tienes mi dinero ahí. Incluso si ya donaste, cuando nos das el dinero, realmente es tu dinero. Y utilizar el mejoramiento progresivo significa que si hay un error en nuestro JavaScript del lado del cliente, aún puedes verlo y usarlo. Muchas cosas, no todo, pero muchas cosas siguen funcionando con el JavaScript, como los formularios y cosas así. Por lo tanto, la mayoría de la aplicación se puede utilizar incluso sin JavaScript. Y eso es cómo el Mejoramiento Progresivo nos está ayudando. Y esto se puede hacer en Remix porque, ya sabes, Remix utiliza enlaces para navegar y el enlace es un ancla y utiliza el componente de formulario, que es una aplicación. Y todo sigue funcionando de esa manera.
En realidad, eso también tiene mucho sentido, porque estás trabajando con ese dinero. Quieres darle al usuario comentarios sobre lo que están haciendo en tu aplicación. Entonces necesitas tener ese Mejoramiento Progresivo. Es como si esto estuviera funcionando en segundo plano, pero no puedes verlo hasta que se haya terminado. Pero vamos a mostrarte progresivamente una actualización optimista con la esperanza de que esos datos regresen, ¿verdad? Sí. Genial. Ahora tenemos un par de preguntas de la audiencia. Chris dijo, ¿tuviste algún problema para convencer a tu equipo de migrar a Remix? Creo que dijiste de Next.js, y ¿cómo lo haces al principio? Comencé a pensar en convencer al equipo de usar Remix. Recién estábamos comenzando el front-end.
Migración a Remix y Estructura de Monorepo
Short description:
Inicialmente construimos una prueba de concepto con enrutadores de React, pero eventualmente decidimos migrar a Remix debido a problemas de rendimiento. El CTO estaba inicialmente indeciso de usar Remix porque era un framework de pago y podría dificultar la contratación. Sin embargo, después de probar Remix durante la temporada navideña, el CTO quedó convencido de sus beneficios. Nuestra aplicación no es un monorepo, sino una carpeta única que contiene todo el código del frontend.
Construimos una prueba de concepto original con enrutadores de React configurados por Rails en tu ruta, y luego necesitábamos pasar a algo mejor. En ese momento, Remix todavía era de pago. Mi CTO no estaba convencido de usarlo porque era de pago, lo que significa que no todos lo conocerían. Sería más difícil contratar a alguien que conozca el framework. Comenzamos a usar Next por eso. Contribuí, uno de mis compañeros de trabajo es uno de los autores originales de NextJS. Comenzamos con Next, luego decidimos migrar a Remix porque comenzamos a tener problemas con el rendimiento de la aplicación. Las páginas de inicio del frontend eran geniales, pero lo que estás en la parte de la aplicación no es tan bueno, especialmente si no usas la mayoría de las cosas del lado del cliente, y eso fue lo que convenció al CTO de probar Remix. Lo probó en la semana entre Navidad y Año Nuevo. Después de eso, regresó de Año Nuevo y básicamente me dijo, sí, Remix es genial. Esta es mi lista de cosas. Aunque me gusta, vamos a migrar a nuestro código, para hacerlo. Es como si no quisieran cambiar a Remix, solo muéstraselo, haz que lo prueben, ¿verdad? Sí, creo que esa es la mejor manera de convencer a alguien de usarlo. Solo pruébalo, muéstralo. Genial, ¿tu aplicación es un monorepo? No es un monorepo, bueno, tenemos un monorepo, pero mi aplicación tiene el frontend en una carpeta que tiene todo del frontend. No se comparte con otros.
Monorepo Importing and Team Size
Short description:
En cuanto al monorepo, no hemos tenido dificultades para importar paquetes de componentes locales en Remix. Tenemos todo el código en la misma aplicación. Tenemos un equipo bastante pequeño de 8 personas trabajando en la base de código migrada. Es fácil convencer a las personas de migrar usando sus propios términos y expresándolo de manera diferente. Remix es fácil de aprender ya que utiliza la plataforma web y JavaScript. Contratar a alguien para trabajar en Remix es más fácil que contratar a alguien para otros frameworks.
partes del monorepo, porque son otros lenguajes. Bueno, tenemos una pregunta que está relacionada con el monorepo, así que si no lo sabes, no te preocupes, pero solo quería hacerla por si acaso. ¿Has tenido dificultades para importar paquetes de componentes locales en Remix en un entorno de monorepo? Sí, no lo hemos intentado, simplemente tenemos todo el código en la misma aplicación. Sí, genial. Así que tampoco tengo experiencia con eso.
De acuerdo, hagamos una última pregunta de Adrian. ¿Cuántas personas están trabajando en la base de código que migraron? Déjame contar. Tenemos 1, 2, 3, 4, 5, 6, 7, 8 personas. Genial. Es un equipo bastante pequeño, ¿verdad? Es bastante fácil convencer a las personas. Y creo que eso es algo que siempre he dicho, como, si estás hablando con un interesado o alguien que no es desarrollador sobre la migración, algo así, quieres asegurarte de usar sus términos y expresarlo de diferentes maneras a como lo harías si estuvieras hablando con un desarrollador. Así que creo que eso es otra cosa a tener en cuenta si estás tratando de convencer a tu empresa de migrar. Sí, además, cuando comenzamos, éramos cuatro personas. Contratamos al resto después de que comenzamos la migración. Y luego Remix, súper rápido. Uno de ellos lo aprendió para la entrevista en una semana, como una semana y dos días, algo así. Ese es otro gran punto, que Remix no tiene muchas cosas específicas de Remix, y utiliza la plataforma web. Así que realmente solo estás aprendiendo JavaScript en su mayor parte. Y React. Creo que eso hace que sea más fácil contratar a alguien para trabajar en Remix que contratar a alguien para trabajar en cualquier otra cosa. No necesitas aprender demasiado, solo aprendes sobre la web en sí misma. Sí, genial. Bueno, creo que eso es todo el tiempo que tenemos para preguntas. Muchas gracias por responder, Sergio, y gracias por unirte hoy. Gracias. Muy bien. Nos vemos.
Remix is a web framework built on React Router that focuses on web fundamentals, accessibility, performance, and flexibility. It delivers real HTML and SEO benefits, and allows for automatic updating of meta tags and styles. It provides features like login functionality, session management, and error handling. Remix is a server-rendered framework that can enhance sites with JavaScript but doesn't require it for basic functionality. It aims to create quality HTML-driven documents and is flexible for use with different web technologies and stacks.
Kent C. Dodds discusses the concept of problem elimination rather than just problem-solving. He introduces the idea of a problem tree and the importance of avoiding creating solutions prematurely. Kent uses examples like Tesla's electric engine and Remix framework to illustrate the benefits of problem elimination. He emphasizes the value of trade-offs and taking the easier path, as well as the need to constantly re-evaluate and change approaches to eliminate problems.
This talk discusses the usage of Microfrontends in Remix and introduces the Tiny Frontend library. Kazoo, a used car buying platform, follows a domain-driven design approach and encountered issues with granular slicing. Tiny Frontend aims to solve the slicing problem and promotes type safety and compatibility of shared dependencies. The speaker demonstrates how Tiny Frontend works with server-side rendering and how Remix can consume and update components without redeploying the app. The talk also explores the usage of micro frontends and the future support for Webpack Module Federation in Remix.
This Talk explores React's internal jargon, specifically fiber, which is an internal unit of work for rendering and committing. Fibers facilitate efficient updates to elements and play a crucial role in the reconciliation process. The work loop, complete work, and commit phase are essential steps in the rendering process. Understanding React's internals can help with optimizing code and pull request reviews. React 18 introduces the work loop sync and async functions for concurrent features and prioritization. Fiber brings benefits like async rendering and the ability to discard work-in-progress trees, improving user experience.
RemixConf EU discussed full stack components and their benefits, such as marrying the backend and UI in the same file. The talk demonstrated the implementation of a combo box with search functionality using Remix and the Downshift library. It also highlighted the ease of creating resource routes in Remix and the importance of code organization and maintainability in full stack components. The speaker expressed gratitude towards the audience and discussed the future of Remix, including its acquisition by Shopify and the potential for collaboration with Hydrogen.
Debugging JavaScript is a crucial skill that is often overlooked in the industry. It is important to understand the problem, reproduce the issue, and identify the root cause. Having a variety of debugging tools and techniques, such as console methods and graphical debuggers, is beneficial. Replay is a time-traveling debugger for JavaScript that allows users to record and inspect bugs. It works with Redux, plain React, and even minified code with the help of source maps.
Durante esta masterclass, los participantes revisarán los patrones esenciales de JavaScript que todo desarrollador debería conocer. A través de ejercicios prácticos, ejemplos del mundo real y discusiones interactivas, los asistentes profundizarán su comprensión de las mejores prácticas para organizar el código, resolver desafíos comunes y diseñar arquitecturas escalables. Al final de la masterclass, los participantes ganarán una nueva confianza en su capacidad para escribir código JavaScript de alta calidad que resista el paso del tiempo. Puntos Cubiertos: 1. Introducción a los Patrones de JavaScript2. Patrones Fundamentales3. Patrones de Creación de Objetos4. Patrones de Comportamiento5. Patrones Arquitectónicos6. Ejercicios Prácticos y Estudios de Caso Cómo Ayudará a los Desarrolladores: - Obtener una comprensión profunda de los patrones de JavaScript y sus aplicaciones en escenarios del mundo real- Aprender las mejores prácticas para organizar el código, resolver desafíos comunes y diseñar arquitecturas escalables- Mejorar las habilidades de resolución de problemas y la legibilidad del código- Mejorar la colaboración y la comunicación dentro de los equipos de desarrollo- Acelerar el crecimiento de la carrera y las oportunidades de avance en la industria del software
En esta masterclass, discutimos los méritos de la arquitectura sin servidor y cómo se puede aplicar al espacio de la IA. Exploraremos opciones para construir aplicaciones RAG sin servidor para un enfoque más lambda-esque a la IA. A continuación, nos pondremos manos a la obra y construiremos una aplicación CRUD de muestra que te permite almacenar información y consultarla utilizando un LLM con Workers AI, Vectorize, D1 y Cloudflare Workers.
Construir aplicaciones web modernas está lleno de complejidad. Y eso solo si te molestas en lidiar con los problemas ¿Cansado de conectar onSubmit a las API del backend y asegurarte de que tu caché del lado del cliente se mantenga actualizada? ¿No sería genial poder utilizar la naturaleza global de CSS en tu beneficio, en lugar de buscar herramientas o convenciones para evitarla o trabajar alrededor de ella? ¿Y qué te parecería tener diseños anidados con una gestión de datos inteligente y optimizada para el rendimiento que simplemente funciona™? Remix resuelve algunos de estos problemas y elimina completamente el resto. Ni siquiera tienes que pensar en la gestión de la caché del servidor o en los conflictos del espacio de nombres global de CSS. No es que Remix tenga APIs para evitar estos problemas, simplemente no existen cuando estás usando Remix. Ah, y no necesitas ese enorme y complejo cliente graphql cuando estás usando Remix. Ellos te tienen cubierto. ¿Listo para construir aplicaciones más rápidas de manera más rápida? Al final de esta masterclass, sabrás cómo:- Crear Rutas de Remix- Estilizar aplicaciones de Remix- Cargar datos en los cargadores de Remix- Mutar datos con formularios y acciones
La web moderna sería diferente sin aplicaciones ricas del lado del cliente respaldadas por potentes frameworks: React, Angular, Vue, Lit y muchos otros. Estos frameworks se basan en JavaScript del lado del cliente, que es su núcleo. Sin embargo, existen otros enfoques para el renderizado. Uno de ellos (bastante antiguo, por cierto) es el renderizado del lado del servidor completamente sin JavaScript. Descubramos si esta es una buena idea y cómo Remix puede ayudarnos con ello? Prerrequisitos- Buen entendimiento de JavaScript o TypeScript- Sería útil tener experiencia con React, Redux, Node.js y escribir aplicaciones FrontEnd y BackEnd- Preinstalar Node.js, npm- Preferimos usar VSCode, pero también se pueden utilizar IDE en la nube como codesandbox (otros IDE también están bien)
- ¿Errores? Cómo renderizar y registrar tus errores del servidor y del clientea - Cuándo devolver errores vs lanzar excepcionesb - Configurar servicios de registro como Sentry, LogRocket y Bugsnag- ¿Formularios? Cómo validar y manejar formularios de varias páginasa - Usar zod para validar los datos del formulario en tu acciónb - Pasar por formularios de varias páginas sin perder datos- ¿Atascado? Cómo solucionar errores o funciones faltantes en Remix para que puedas continuara - Usar patch-package para solucionar rápidamente tu instalación de Remixb - Mostrar herramienta para gestionar múltiples parches y seleccionar solicitudes de extracción abiertas- ¿Usuarios? Cómo manejar aplicaciones de varios inquilinos con Prismaa - Determinar el inquilino por el host o por el usuariob - Base de datos múltiples o base de datos única/múltiples esquemasc - Asegura que los datos del inquilino siempre estén separados de los demás
Sumérgete en el mundo de la IA con nuestro masterclass interactivo diseñado específicamente para desarrolladores web. "Masterclass: Integrando LangChain con JavaScript para Desarrolladores Web" ofrece una oportunidad única para cerrar la brecha entre la IA y el desarrollo web. A pesar de la prominencia de Python en el desarrollo de IA, el vasto potencial de JavaScript sigue siendo en gran medida inexplorado. Este masterclass tiene como objetivo cambiar eso.A lo largo de esta sesión práctica, los participantes aprenderán cómo aprovechar LangChain, una herramienta diseñada para hacer que los modelos de lenguaje grandes sean más accesibles y útiles, para construir agentes de IA dinámicos directamente dentro de entornos JavaScript. Este enfoque abre nuevas posibilidades para mejorar las aplicaciones web con funciones inteligentes, desde el soporte al cliente automatizado hasta la generación de contenido y más.Comenzaremos con los conceptos básicos de LangChain y los modelos de IA, asegurando una base sólida incluso para aquellos nuevos en IA. A partir de ahí, nos sumergiremos en ejercicios prácticos que demuestran cómo integrar estas tecnologías en proyectos reales de JavaScript. Los participantes trabajarán en ejemplos, enfrentando y superando los desafíos de hacer que la IA funcione sin problemas en la web.Este masterclass es más que una experiencia de aprendizaje; es una oportunidad de estar a la vanguardia de un campo emergente. Al final, los asistentes no solo habrán adquirido habilidades valiosas, sino que también habrán creado funciones mejoradas con IA que podrán llevar a sus proyectos o lugares de trabajo.Ya seas un desarrollador web experimentado curioso acerca de la IA o estés buscando expandir tus habilidades en áreas nuevas y emocionantes, "Masterclass: Integrando LangChain con JavaScript para Desarrolladores Web" es tu puerta de entrada al futuro del desarrollo web. Únete a nosotros para desbloquear el potencial de la IA en tus proyectos web, haciéndolos más inteligentes, interactivos y atractivos para los usuarios.
Comments