Video Summary and Transcription
La charla discute la directiva defer en GraphQL, que permite a los clientes especificar partes de una consulta que se pueden entregar de forma incremental. Aborda el problema de los campos con mayor latencia y aún así tener una única respuesta. La charla explora diferentes enfoques para resolver este problema, como la división de consultas y la precarga. También cubre ejemplos de uso de la directiva defer para renderizado parcial y carga perezosa, así como su uso en mutaciones. La charla enfatiza la importancia del rendimiento para la experiencia del usuario y proporciona recursos para una mayor exploración.
1. Introducción a la Directiva Defer
Hola a todos. Mi nombre es Lucas Ledbetter y soy un arquitecto de soluciones aquí en Apollo. Estoy muy emocionado de estar aquí hoy, al menos virtualmente, para hablar sobre la directiva defer y lo que puede significar para sus clientes. GraphQL requiere que todo el cuerpo se envíe como una única respuesta. Algunos campos requieren tiempo adicional para resolverse. El cliente debería poder renderizar parcialmente los datos a medida que llegan.
Mi nombre es Lucas Ledbetter y soy un arquitecto de soluciones aquí en Apollo. Estoy muy emocionado de estar aquí hoy, al menos virtualmente, para hablar sobre la directiva defer y lo que puede significar para sus clientes.
Para tener una imagen completa, necesitaremos cubrir algunos detalles de fondo antes de profundizar en qué es exactamente defer. Por último, daré algunos ejemplos que muestran dónde defer puede ser una herramienta increíblemente poderosa en su arsenal para ayudar a sus clientes a brindar una mejor experiencia de usuario.
Entonces, retrocediendo un poco, es posible que sepa que GraphQL requiere que todo el cuerpo se envíe como una única respuesta. Esto es genial para la mayoría de las consultas, ya que su interfaz de usuario espera que todos los datos estén allí. Seguramente no querría devolver solo algunos de los datos para un usuario en una página de perfil de usuario, por ejemplo. A medida que su gráfico crece, se da cuenta de que no todos los campos están construidos de la misma manera. Algunos campos requieren tiempo adicional para resolverse por una razón u otra. Para muchas organizaciones, esto se debe simplemente a la escala. Pero para otras, podría estar relacionado con un servicio de terceros del que no tienen un control completo, lo que implica mantener los tiempos de respuesta de las otras partes, o una serie de otras razones. Independientemente de por qué lleva más tiempo, se dan cuenta de que la solicitud de esos campos hace que toda la respuesta se ralentice. A medida que los clientes comienzan a acceder a esos campos, comienzan a ver que la latencia general del gráfico aumenta como resultado, lo cual no es ideal y significa que la experiencia de usuario se ve afectada. El cliente debería poder renderizar parcialmente los datos a medida que llegan. Pero desafortunadamente no es posible con una única solicitud.
2. Enfoques Diferentes para Abordar el Problema
Las empresas idearon dos enfoques diferentes para resolver este problema. La primera solución es la división de consultas, que requería que los clientes orquestaran múltiples consultas. Esto abordaba el problema del eslabón más débil en GraphQL tradicional, pero tenía limitaciones de rendimiento y contexto. El prefetching se convirtió en otro enfoque popular, haciendo suposiciones sobre la intención del usuario y solicitando datos anticipadamente. Sin embargo, esto generaba una carga adicional en los servidores y se basaba en conjeturas informadas.
Para resolver este creciente problema, las empresas idearon dos enfoques diferentes. Ambos abordaban algunos de los problemas, pero cada uno tenía sus compensaciones. La primera solución que veremos es la división de consultas. Esta solución consistía en dividir la consulta única en múltiples consultas y requería que los clientes orquestaran las respuestas. Esto suena mucho a uno de los problemas para los que se creó GraphQL. Sin embargo, esto abordaba el problema del eslabón más débil que afectaba a GraphQL tradicional, hasta que los problemas de rendimiento puedan mitigarse o abordarse en el servidor.
Además de tener que manejar las respuestas en el cliente, también requería que el servidor maneje múltiples consultas únicas de los clientes, cada una con la sobrecarga tradicional de HTTP y GraphQL, además de no poder utilizar los datos ya obtenidos, como el tipo de datos evidente. Perder ese contexto adicional, especialmente para los campos que necesitan realizar muchas llamadas a otros servicios, podría resultar bastante costoso.
Por otro lado, el prefetching se convirtió en otra forma popular de abordar este problema. Al solicitar datos anticipadamente, es posible mitigar las preocupaciones de rendimiento haciendo suposiciones sobre la intención del usuario. Por ejemplo, obtener la información de pago del usuario antes de llegar a la página de finalizar la compra. Esto tenía la ventaja adicional de seguir siendo una única solicitud. Sin embargo, la experiencia del usuario en el cliente no cambia mucho, si es que cambia, cuando funciona. Como es obvio, los servidores deben manejar esta carga adicional para una interacción asumida, incluso si el usuario nunca interactuó con los datos devueltos, lo que hace que esto sea en su mayoría una conjetura informada.
3. Understanding the Defer Directive in GraphQL
Ambas soluciones avanzaron hacia el objetivo final de una buena experiencia de usuario, pero nunca llegaron completamente. Esto nos lleva a la directiva defer. Como podrás haber adivinado, defer es una posible solución al problema continuo de los campos con mayor latencia mientras se tiene una única respuesta. Defer es una directiva utilizada por los clientes para informar a los servidores de GraphQL que las solicitudes pueden entregarse incrementalmente al especificar las partes de una consulta que se devolverán más tarde. A día de hoy, esta directiva no forma parte de la especificación oficial de GraphQL. Sin embargo, ya ha sido utilizada por varias empresas en producción. Actualmente, se encuentra en el grupo de trabajo con un RFC de acceso público que cubre los detalles de la directiva y al final de la presentación proporcionaré un enlace al RFC. Al hacer que defer sea indicado por el cliente en lugar del servidor, ahora podemos permitir que los clientes informen al servidor qué campos pueden ser respondidos más tarde y cuáles no. Entonces, ¿cómo funciona realmente esta directiva? ¿Es magia? Bueno, no es magia, pero puede parecerlo después de trabajar con ella por primera vez. Hoy cubriremos esto a un nivel alto por cuestiones de tiempo, pero hay excelentes charlas y publicaciones que cubren los aspectos técnicos más detallados de la directiva, así como el RFC del Grupo de Trabajo. Considera el esquema básico de un sitio ficticio de redes sociales, que tiene una consulta para devolver una lista de usuarios, así como un tipo de usuario con una lista de amigos. En este ejemplo, la empresa que ejecuta este esquema de GraphQL nota que el campo de amigos no es tan eficiente como debería ser. Ahora, dada la consulta a la izquierda para obtener la lista de usuarios junto con sus amigos, enviamos las solicitudes y tarda un segundo en obtener la respuesta completa. Esto no es ideal, y como desarrollador de cliente, podríamos renderizar parcialmente los datos del usuario antes de renderizar la lista de amigos para cada usuario.
Ambas soluciones avanzaron hacia el objetivo final de una buena experiencia de usuario, pero nunca llegaron completamente. Esto nos lleva a la directiva defer. Como podrás haber adivinado, defer es una posible solución al problema continuo de los campos con mayor latencia mientras se tiene una única respuesta.
La primera pregunta que te podrías hacer es, ¿qué es esta cosa llamada directiva defer? Y es una gran pregunta. Defer es una directiva utilizada por los clientes para informar a los servidores de GraphQL que las solicitudes pueden entregarse incrementalmente al especificar las partes de una consulta que se devolverán más tarde. O en otras palabras, al retrasar la respuesta.
A día de hoy, esta directiva no forma parte de la especificación oficial de GraphQL. Sin embargo, ya ha sido utilizada por varias empresas en producción. Actualmente, se encuentra en el grupo de trabajo con un RFC de acceso público que cubre los detalles de la directiva y al final de la presentación proporcionaré un enlace al RFC.
Como un pequeño paréntesis, todos hemos visto directivas utilizadas en aplicaciones del lado del servidor. Desde información de formato, hasta notación de Apollo Federation y más. Sin embargo, la especificación de GraphQL también menciona la capacidad de usarlas en la propia consulta. En general, soy un gran defensor de las directivas ejecutables o directivas del lado del cliente. Permiten que los clientes proporcionen un contexto adicional para el uso y procesamiento de la directiva, y no simplemente una notación en el esquema sobre el comportamiento esperado como ocurre con las directivas del lado del servidor. Hemos visto directivas del lado del cliente en el pasado con cosas como skip e include, tal como se definen en la especificación, y defer es muy similar.
Entonces, ¿por qué menciono esto? Al hacer que defer sea indicado por el cliente en lugar del servidor, ahora podemos permitir que los clientes informen al servidor qué campos pueden ser respondidos más tarde y cuáles no. Ahora las solicitudes son las mismas. Pueden estar ubicadas para porciones de una consulta en un componente, pero esa misma consulta puede ser devuelta como una única respuesta en otro componente. Ese contexto es difícil de transmitir sin defer. Ahora volvamos a la programación regular.
Entonces, ¿cómo funciona realmente esta directiva? ¿Es magia? Bueno, no es magia, pero puede parecerlo después de trabajar con ella por primera vez. Hoy cubriremos esto a un nivel alto por cuestiones de tiempo, pero hay excelentes charlas y publicaciones que cubren los aspectos técnicos más detallados de la directiva, así como el RFC del Grupo de Trabajo.
Considera el esquema básico de un sitio ficticio de redes sociales, que tiene una consulta para devolver una lista de usuarios, así como un tipo de usuario con una lista de amigos. En este ejemplo, la empresa que ejecuta este esquema de GraphQL nota que el campo de amigos no es tan eficiente como debería ser. Quiero llamar explícitamente la atención sobre algo aquí. El campo de amigos, aunque devuelve una lista de usuarios no nulos, en sí mismo es anulable. Esto es importante y es algo de lo que hablaremos en un momento para explicar por qué es así.
Ahora, dada la consulta a la izquierda para obtener la lista de usuarios junto con sus amigos, enviamos las solicitudes y tarda un segundo en obtener la respuesta completa. Esto no es ideal, y como desarrollador de cliente, podríamos renderizar parcialmente los datos del usuario antes de renderizar la lista de amigos para cada usuario. En un perfil de usuario, probablemente rendericemos su nombre de usuario, información de contacto y más.
4. Usando la Directiva Defer en las Consultas
Hemos modificado la consulta para incluir la nueva directiva deferida. La respuesta multipartida incluye un campo has-next para indicar más respuestas y un campo incremental para datos adicionales. La respuesta se muestra en un gif, con una respuesta inmediata en aproximadamente 8 milisegundos y el resto llega más tarde.
Bien, la lista de amigos puede cargarse cuando llegue, en lugar de bloquear todo el proceso de renderizado. Así que hemos modificado la consulta para incluir la nueva directiva deferida. Es posible que primero notes que la directiva está en un fragmento en línea. Esto se debe a que el RFC actual establece que solo debe incluirse en fragmentos o fragmentos en línea. Ahora, si ejecutas esta consulta, obtendremos una respuesta multipartida que se muestra a la izquierda. La primera respuesta tiene un nuevo campo pero, por lo demás, contiene la misma estructura que la respuesta normal de GraphQL, las respuestas posteriores tienen un nuevo formato. Si bien no es fundamental entender todo esto, hay dos partes que me gustaría resaltar. En primer lugar, cada respuesta tiene el campo has-next indicado en azul que indica al cliente que hay más respuestas en camino. Una vez que es falso, se ha enviado toda la respuesta. Cada respuesta posterior tiene un campo incremental que contiene el Delta y la ruta hacia los datos adicionales. Como puedes ver, la información adicional aquí se inserta en el array de usuarios en el índice 0. Ahora, para ponerlo todo junto, aquí tienes un breve gif de los resultados. Puedes ver que obtenemos una respuesta inmediata en aproximadamente 8 milisegundos y luego, un segundo después, obtenemos el resto. Si tienes curiosidad, el gif es de un sandbox de Apollo y ahora admite Defer de forma nativa incluyendo una línea de tiempo para desplazarse por los diferentes estados de la respuesta y podría ser una herramienta útil para comprender cómo se está produciendo tu respuesta diferida.
5. Comprendiendo la Importancia del Rendimiento
Entonces, al comenzar a pensar en defer, es posible que notes que en realidad no mejora el rendimiento. Pero para realmente adentrarnos en cómo puede ayudar, primero debes preguntarte: ¿Por qué te importa el rendimiento? Esta es una pregunta que tengo que hacer a varias empresas para obtener una respuesta por una u otra razón. Para algunos, se trata de medir cómo se desempeñan terceros dentro de su gráfico. Para otros, se trata de cómo va la experiencia del usuario. Sin embargo, la realidad es que la mayoría de las veces los usuarios son los más afectados por los gráficos de rendimiento.
Entonces, al comenzar a pensar en defer, es posible que notes que en realidad no mejora el rendimiento. Después de todo, aún estás esperando una respuesta. Pero para realmente adentrarnos en cómo puede ayudar, primero debes preguntarte: ¿Por qué te importa el rendimiento? Esta es una pregunta que tengo que hacer a varias empresas para obtener una respuesta por una u otra razón. Para algunos, se trata de medir cómo se desempeñan terceros dentro de su gráfico. Para otros, se trata de cómo va la experiencia del usuario. Sin embargo, la realidad es que los usuarios son los más afectados por los gráficos de rendimiento. Muchos equipos de clientes miden el tiempo hasta el primer byte, el tiempo hasta la interactividad, el tamaño de carga útil o cualquier otra métrica. Pero Defer se enfoca específicamente en el tiempo hasta el primer byte y puede interferir con el tiempo hasta la interactividad, dependiendo de cómo se implemente.
6. Ejemplos de Defer en Acción
Vamos a explorar ejemplos de Defer en acción y su impacto en la experiencia del usuario. Comenzaremos con una forma sencilla de utilizar Defer para la representación parcial o la carga perezosa. Al agregar campos adicionales al esquema, podemos representar primero la información del perfil del usuario y cargar los amigos más tarde.
Entonces, veamos algunos ejemplos de Defer en acción y hablemos sobre cómo pueden mejorar la experiencia del usuario. Primero, queremos analizar una forma relativamente sencilla de aprovechar Defer como una forma de hacer representación parcial o carga perezosa. Volviendo a nuestro esquema anterior, hemos agregado algunos campos más al sitio de redes sociales ficticio. Como se mencionó anteriormente, podemos representar correctamente la información del perfil del usuario rápidamente antes de agregar a los amigos más tarde. Ahora, veremos las dos consultas lado a lado. Ten en cuenta que hemos agregado la URL del avatar, el nombre de usuario y el título a la consulta base en ambos casos, ya que los necesitamos de inmediato. De lo contrario, diferiremos la lista de amigos, igual que antes.
7. Usando la Directiva Defer para Mejoras en la Experiencia del Usuario
Ahora, disculpen mi terrible maqueta. En la consulta normal, estamos bloqueados por los campos más bajos, que en este caso es el campo de amigos, y no podemos representar ningún otro dato hasta que se haya terminado. Pero pueden ver de inmediato que obtenemos la información del perfil en las solicitudes diferidas y podemos ver claramente que obtenemos nuestros datos rápidamente. Nuestro tiempo para el primer byte ha disminuido significativamente y, probablemente, aún más importante, el tiempo para la actividad de error también ha disminuido. Ahora, yendo un paso más allá, hemos agregado parámetros a nuestro campo de amigos para especificar la cantidad de amigos para mostrar y un desplazamiento. Usando defer y aliasing en GraphQL, podemos cargar rápidamente los primeros 10 amigos y luego desplazar los amigos restantes en la declaración diferida. Estas optimizaciones son posibles gracias al uso de defer. También es posible tener más de un defer o incluso anidar defers. En este ejemplo, tenemos un usuario con un perfil de empresa asociado. Podemos diferir cada paso para comenzar a devolver datos a lo largo de la ruta, representando los datos a medida que llegan. Ahora consideremos algunas otras posibles mejoras en la experiencia del usuario. Obtener datos es sencillo, pero ¿qué pasa con cambiar datos? Las mutaciones también están en GraphQL.
No soy definitivamente un diseñador de UX. En la consulta normal, estamos bloqueados por los campos más bajos, que en este caso es el campo de amigos, y no podemos representar ningún otro dato hasta que se haya terminado. Pero pueden ver de inmediato que obtenemos la información del perfil en las solicitudes diferidas y podemos ver claramente que obtenemos nuestros datos rápidamente. Nuestro tiempo para el primer byte ha disminuido significativamente, y probablemente aún más importante, el tiempo para la actividad de error también ha disminuido. El usuario puede ver y participar con partes de los datos antes de que se envíe la respuesta completa.
Ahora, yendo un paso más allá, tal vez nuestra empresa identificó que el campo de amigos no estaba, o se ralentizaba según la cantidad de amigos seleccionados por cualquier motivo. Hay otro camino potencial que podríamos tomar. Ahora hemos agregado dos nuevos parámetros a nuestro campo de amigos en el esquema mostrado a la izquierda para permitirnos especificar la cantidad de amigos para mostrar y un desplazamiento. Usando defer y aliasing en GraphQL, ahora podemos cargar rápidamente los primeros 10 amigos y luego desplazar los amigos restantes en la declaración diferida. Tradicionalmente, esto consistiría en múltiples consultas para obtener los otros amigos a representar, permitiendo que el servidor ejecute estas consultas en paralelo brinda otros beneficios de rendimiento más allá de las mejoras simples de UX. De hecho, esto es bastante similar a la directiva de transmisión que es parte del mismo grupo de trabajo que la directiva defer pero se sale un poco del alcance de la discusión de hoy. En resumen, utiliza gran parte de los mismos patrones que defer para enviar listas grandes de forma incremental con una lista inicial de elementos enviados. Cada fragmento subsiguiente en la respuesta multipartida contendría entradas adicionales a la lista hasta que se complete. Hay una serie de excelentes charlas y documentos sobre Stream y recomiendo encarecidamente echar un vistazo si enviar listas grandes es una preocupación para su organización. Estos tipos de optimizaciones son posibles gracias al uso de defer. Y a medida que avanzas en el camino de considerar defer como una solución, considera cómo también puedes aprovechar otros aspectos de GraphQL para combinar características. Es probable que te des cuenta de que puedes crear soluciones con retornos diferidos que antes no eran posibles y que pueden ayudar a mejorar el rendimiento del lado del servidor. Ten en cuenta que también es posible tener más de un defer o incluso anidar defers. En este ejemplo, tenemos un usuario que tiene un perfil de empresa asociado. Esa empresa también lista a su propietario. En este caso, es bastante posible que el servicio del usuario se comunique con el servicio de la empresa, que luego vuelve al servicio del usuario para resolver la información del propietario. Estos saltos llevan tiempo. Y en este caso, podemos diferir cada paso para comenzar a devolver datos a lo largo de la ruta, representando datos a medida que llegan. Es bastante posible que el nombre de la empresa no sea inmediatamente crítico en un perfil y que la lista de propietarios no sea importante en absoluto.
Ahora consideremos algunas otras posibles mejoras en la experiencia del usuario. Obtener datos es bastante sencillo. Todos podemos imaginar cómo hacer una carga parcial ya que había una solución antes de defer. Simplemente usaríamos múltiples consultas o consultas por componente en React. Pero ¿qué pasa con cambiar datos? Las mutaciones también están en GraphQL.
8. Directiva Defer y Mutaciones
Defer admite mutaciones, lo que permite devolver un ID transaccional que se puede utilizar más tarde. Los errores son una realidad y, cuando ocurren durante una declaración diferida, son similares a las promesas de JavaScript. Se deben considerar los estados de error parciales y se deben evaluar las estrategias de reintento caso por caso. Codificar los estados de error esperados en el esquema puede crear una experiencia más limpia para los equipos de clientes.
Y afortunadamente, defer también admite mutaciones. Como ejemplo, aquí hay una muestra de mutación para un servicio de pago ficticio. Desglosando esto, devuelve un ID de pago y un usuario, así como una interfaz de estado de pago. Esta interfaz indica ya sea estados de éxito o de fallo. Como nota al margen, personalmente me encanta codificar errores y esquemas para cosas como esta. Y en realidad, hablaremos de errores en un momento. Profundizando un poco más en esto, para las personas que trabajan con comercio electrónico, saben que los pagos pueden llevar tiempo. Defer nos permite devolver un ID transaccional, que podemos utilizar más tarde, como cuando el usuario actualiza el procesamiento y muestra una pantalla de carga. Una vez que hemos obtenido un resultado del campo de estado de pago, podemos representarlo adecuadamente. Ya sea éxito, en cuyo caso tenemos el monto construido, o es un fallo, en cuyo caso tenemos el mensaje o la razón en este caso. Desde la perspectiva del usuario, sin embargo, probablemente podríamos representar el resultado correcto sin suscripción o sondeo para obtener un estado actualizado. En su lugar, utilizamos la conexión HTTP existente para enviar la información a nuestros clientes para su uso posterior. Y por mucho que me encante hablar de codificar errores en su esquema y dar un reconocimiento a Saucer Solomon por su excelente charla sobre el tema. Los errores son una realidad. Por mucho que nos esforcemos por construir código sin errores, codificar todos los diversos estados de error en nuestro esquema y hacer pruebas para evitarlos, y a medida que comenzamos a hablar de rendimiento, los errores son un tema natural de discusión, ya que también son una medida de éxito y experiencia del usuario. Con eso en mente, podrías preguntarte qué sucede cuando ocurre un error durante una declaración diferida. Bueno, para verlo, tenemos esta consulta ciertamente no sospechosa en absoluto para devolver definitivamente un error en un estado diferido. Quiero decir, ¿quién podría haberlo visto venir? Pero hablando en serio, los primeros errores en los diferidos son extraños. La mejor analogía que tengo es que son muy similares a las promesas de JavaScript. Estás esperando que el resultado llegue en algún momento indefinido en el futuro y debes verificar que no sea rechazado o haya ocurrido un error en este caso. Por lo tanto, para los equipos de clientes que están viendo esto, requiere que piensen más cuidadosamente en los estados de error parciales. Anteriormente, podrías volver a intentar toda la solicitud si veías un error, pero en el mundo de FUR, es posible que tengas un estado de éxito inicial pero un estado de error en las solicitudes posteriores. Por lo tanto, debes considerar tu estrategia de reintento caso por caso. Para demostrar esto, a la derecha, tenemos un GIF de una bandeja de entrada de pólizas una vez más, inmediatamente notas que no tenemos ningún error y luego llega uno y coincide con el formato que ya vimos. Al revisar la línea de tiempo, podemos ver que la primera respuesta fue excelente, sin errores, pero la segunda respuesta tiene un error y seis diferidos. Si tienes dos declaraciones diferidas que generan errores, obtendrás múltiples errores en la clave de error, al igual que en una respuesta gráfica normal. Y para tocar brevemente algunas consideraciones que debes tener al usar defer en relación con los errores, recomendamos codificar cualquier error esperado, estados de fallo como `usuario no encontrado` en tu esquema siempre que sea posible. Esto crea una experiencia más limpia para tus equipos de clientes cuando obtienen estados de fallo y un primer fragmento, evitando que tengan que analizar los errores. Sin embargo, cuando no puedes hacerlo, espera todo lo que puedas. Ya manejas los errores dentro de tu cliente verificando a lo largo de tus respuestas diferidas para ver si te encuentras con errores.
9. Manejo de Datos Parciales y Comportamiento de Errores
Por último, si tienes datos parciales, utiliza esos datos parciales y no expulses al usuario de la página si una pieza no se carga. Defer admite tanto campos nulos como no nulos, pero el comportamiento de los errores difiere según cómo uses defer y cómo se tipifique el campo.
Por último, si tienes datos parciales, utiliza esos datos parciales y no expulses al usuario de la página si una pieza no se carga. Por obvio que parezca, defer se utiliza mejor para datos de baja prioridad, cosas que pueden esperar a ser devueltas y, como tal, volver a intentar u otros mecanismos pueden ayudar a asegurar que la experiencia del usuario siga siendo excelente. Y si recuerdas antes, mencioné explícitamente que el campo friends de sus sitios de redes sociales era nulo. Defer admite tanto campos nulos como no nulos, pero el comportamiento de los errores difiere según cómo uses defer y cómo se tipifique el campo. Esto difiere de GraphQL tradicional. Así que es información importante para saber. Nuestra lista de amigos era un campo nulo con una lista no nula de usuarios. La consulta utilizada antes es genial. Es probable que, es probable que la solicitud sea una solicitud de todo o nada donde si no logramos obtener los amigos por alguna razón, el campo permanecerá nulo como puedes ver aquí.
10. Understanding Defer Behavior and Implementation
En una consulta normal, si el campo friends es nulo, obtenemos un objeto de datos vacío. Sin embargo, con las declaraciones diferidas, recibimos una respuesta parcial sin el campo friends. Lo mismo ocurre al diferir campos específicos. Ten cuidado con la nulabilidad, ya que defer introduce complejidad adicional. Apollo admite defer en sus clientes, lo que facilita su uso en la práctica. Apollo Studio y Apollo Sandbox son excelentes herramientas para probar defer. Apollo también ha lanzado una versión de defer para gráficos federados, que no requiere soporte adicional. Si estás utilizando federación, considera probar defer. La implementación es independiente de la biblioteca. Agregar federación y declaración de entidades puede habilitar defer sin muchos cambios en el código de tu servidor.
Genial, ahora qué sucede si el campo friends es nulo, no nulo? En una consulta normal, obtenemos un objeto de datos vacío ya que un campo no nulo devuelve nulo. ¿Y qué hay de las declaraciones diferidas? Podrías esperar que suceda lo mismo. Sin embargo, obtenemos una respuesta parcial sin el campo friends pero incluyendo el campo ID. Este es un aspecto importante a considerar al tratar con clientes que utilizan defer. El comportamiento de errores cambia en comparación con GraphQL tradicional y debes tener en cuenta este cambio al migrar al uso de defer en tus consultas.
Lo mismo también se aplica al diferir campos específicos. Por ejemplo, tienes una consulta para obtener un usuario y su URL de avatar, que proviene de un servicio que no es 100% confiable. Este campo necesita una respuesta, sin embargo, lo marcamos como no nulo para que los clientes puedan esperar que exista. Igual que antes, la consulta a la izquierda no está diferida. Y como era de esperar, obtenemos un objeto de datos vacío. Ahora, con el defer, obtenemos nuevamente el objeto parcial. Teniendo todo esto en cuenta, mi recomendación es la siguiente, ten cuidado con la nulabilidad ya que defer introduce complejidad adicional en la respuesta. Simplemente ten en cuenta que esto existe tal como está en el RFC y estarás bien.
Y mientras hablamos de qué es defer y cómo puedes usarlo en principio, utilizarlo en la práctica es afortunadamente bastante sencillo. Apollo anunció recientemente el soporte para defer en sus clientes de React y Clon, con soporte para iOS próximamente. Para aquellos que consideran defer, esto puede ser de gran ayuda si actualmente estás utilizando los clientes de Apollo, ya que defer se puede integrar en aplicaciones existentes sin necesidad de reescribir todo el código. Y una vez que tienes un cliente que admite defer, simplemente necesitas reescribir tus consultas teniendo en cuenta el defer. Como se mencionó anteriormente, Apollo Studio y Apollo Sandbox pueden ser excelentes formas de probar defer y ver cómo funciona en tu gráfico y asegurarte de que hace lo que esperas. De hecho, eso es lo que estás viendo a la derecha. Es el ejemplo anidado de defer que vimos antes. Apollo también ha lanzado una versión de defer para organizaciones que utilizan un gráfico federado y esto es especialmente único ya que no requiere ningún soporte más allá de poder resolver entidades federadas. No tendré tiempo para profundizar en esto, pero la versión resumida es la siguiente. Si estás utilizando federación y tienes aunque sea un interés remoto en defer y lo que puede ofrecer para tus clientes, pruébalo. La implementación es independiente de la biblioteca. Entonces, incluso si tu biblioteca de subgráficos no lo admite de forma nativa, esto puede habilitarlo siempre y cuando estés utilizando el enrutador de Apollo para servir tu supergráfico. Para resumir cómo lo hace esto, el enrutador aprovecha las relaciones de entidades existentes y gestiona el proceso asíncrono de obtener los datos por ti. Por lo tanto, no se necesitan subgráficos para manejar el envío de las respuestas como multipartes. Si actualmente no tienes un entorno federado, agregar federación y declaración de entidades, que es solo sintaxis, es una forma sencilla de utilizar el enrutador como una forma de obtener defer sin muchos cambios en el código de tu servidor. Hemos visto lo genial que puede ser defer.
11. Consideraciones y Recursos
Considera las experiencias que estás generando actualmente y qué casos de uso podrían beneficiarse al ser diferidos. Defer es impulsado por el cliente y se utiliza mejor para datos de menor prioridad. No resolverá tus preocupaciones de rendimiento del lado del servidor. Defer es una herramienta poderosa para tus consumidores y debería aprovecharse si es posible. Participa en la comunidad de gráficos y brinda comentarios. Recursos: RFC, charla de Solomon en redes sociales, charla de 200 OK, documentación del cliente Apollo React, soporte de defer en Apollo Router Federation. Gracias por estar aquí.
También resuelve muchos problemas bastante complejos de manera declarativa, aprovechando las fortalezas de GraphQL. Sin embargo, al mismo tiempo, considera las experiencias que estás generando actualmente y qué casos de uso podrían beneficiarse al ser diferidos. Hemos visto ejemplos de cómo hacer esto. Uno, donde se solucionó un problema para el equipo, y otro donde se necesitaba modificar el esquema para acomodar el defer y brindar una mejor experiencia al cliente. Teniendo en cuenta esas experiencias, puedes asegurarte de que tu esquema siga siendo expresivo y al mismo tiempo permita el uso de defer como opción para mejorar la experiencia del usuario.
Finalmente, como se mencionó antes, defer es impulsado por el cliente. Ellos serán los más conscientes de qué casos de uso pueden ser impulsados por defer. Hemos visto que defer se utiliza mejor para datos de menor prioridad. Por lo tanto, simplemente agregar defer a una consulta no proporcionará muchos beneficios. Asegúrate de utilizar defer con cuidado y asegúrate de que tenga sentido hacerlo cuando lo uses. Y aunque puedes mejorar la experiencia del usuario y el rendimiento de los clientes con defer, no es una panacea. No resolverá tus preocupaciones de rendimiento del lado del servidor y debe tratarse como tal. Identificar y resolver problemas de rendimiento del lado del servidor también puede eliminar la necesidad de utilizar defer. Por lo tanto, hacer ambas cosas puede ayudar a que tu gráfico sea más eficiente y tenga un mejor rendimiento tanto para los clientes como para los servidores.
Y así, algunas reflexiones finales al respecto. En primer lugar, defer es una herramienta poderosa para tus consumidores y tu gráfico, y debería aprovecharse si es posible. Hay muchas formas de mejorar la experiencia del usuario utilizando defer. Y en ese sentido, aunque la especificación es nueva, ya hay algunas bibliotecas que la admiten y Apollo anunció recientemente el soporte para organizaciones que utilizan un gráfico federado, como se mencionó anteriormente. Y mi último punto hoy es este. Si estás interesado en defer pero no cumple con tus requisitos o sientes que se puede mejorar, participa. La comunidad de gráficos es amplia y profunda, y los grupos de trabajo siempre pueden recibir más comentarios sobre casos de uso específicos, inquietudes y más. Participa activamente si puedes. Por último, algunos recursos como se mencionó, tenemos el enlace al RFC, la charla de Solomon en redes sociales, la charla de 200 OK sobre la codificación de errores en tu esquema, la documentación del cliente Apollo React que se utilizó para demostrar defer anteriormente, así como el soporte de defer en Apollo Router Federation. Con eso, gracias. Puedes contactarme en Twitter como elevator y mi correo electrónico es Lucas en Apollo graphical.com. Hola a todos. Encantado de conocerlos. Gracias por unirse al tema de hoy. Genial. Muchas gracias por estar aquí.
Using Defer Directive and Other Approaches
Solo un recordatorio para todos, pueden unirse al canal de preguntas y respuestas de Andromeda en Discord para hacer sus preguntas a Lucas aquí en esta sesión de preguntas y respuestas, pero comencemos echando un vistazo a las respuestas a la pregunta de la encuesta. Parece que la mayoría de las empresas actualmente manejan los campos lentos esperando la respuesta o dividiendo la consulta y realizando una precarga cuando sea posible. Defer no reemplaza necesariamente estos enfoques, ya que hay casos de uso donde las consultas divididas o la precarga pueden ser más adecuadas. La implementación de defer es un proceso incremental y requiere soporte del servidor. Es importante medir el éxito y los beneficios de defer para su caso de uso específico. Herramientas como el enrutador y la herramienta de perfilado de React pueden ayudar con la implementación y la medición del tiempo de renderizado. Otros enfoques como la directiva de transmisión también pueden abordar problemas de rendimiento.
Solo un recordatorio para todos, pueden unirse al canal de preguntas y respuestas de Andromeda en Discord para hacer sus preguntas a Lucas aquí en esta sesión de preguntas y respuestas, pero comencemos echando un vistazo a las respuestas a la pregunta de la encuesta.
Entonces, nuevamente, la pregunta que teníamos era cómo manejan actualmente los campos lentos en su gráfico. Y parece que ahora hay una respuesta bastante abrumadora de simplemente esperar la respuesta. Un poco detrás de eso está dividir la consulta y realizar una precarga cuando sea posible, pero Lucas, ¿qué opinas sobre los resultados? ¿Está alineado con lo que esperabas? Sí, seguro. Creo que en general, vemos muchas empresas haciendo esto donde actualmente no es factible o posible orquestar las respuestas para manejar consultas divididas o hacer suposiciones sobre la interacción del usuario que puede no tener datos allí. Y en general, simplemente esperamos a que aparezcan esos campos lentos y luego los renderizamos cuando los obtenemos.
Sí, y para responder una pregunta aquí de la audiencia, ¿defer reemplaza cosas como la división de consultas o la precarga? No reemplaza necesariamente el cien por ciento del tiempo, hay ciertamente casos de uso para manejar ambas situaciones. Por ejemplo, es posible que no desee solicitar los datos todo el tiempo. Puede haber un campo extenso que el usuario necesita y puede ser necesario en la página en algún momento. Por ejemplo, si se desplazan hacia abajo. Entonces, las consultas divididas o la precarga podrían ser una solución más adecuada, pero en general, defer puede ayudar con la mayoría de estos casos.
Sí, y cuando hablas de implementar algo como defer, ¿hay áreas específicas en las que quieras probarlo primero, o hay una forma de hacer algo como una prueba de concepto o implementarlo en una base de código? ¿O generalmente ves que las personas lo hacen de una vez? Sí, definitivamente es un proceso incremental. No vemos que las personas de repente agreguen defer a cada consulta que hacen por varias razones. Principalmente, el hecho de que defer requiere soporte del servidor, y el soporte del servicio puede variar según los lenguajes. Sé que escuchamos que GraphQL Yoga, por ejemplo, lo admite ahora. Sin embargo, en el lado de Apollo, acabamos de introducir el soporte para defer basado en entidades. Entonces, si estás utilizando Federation, esto acaba de estar disponible. Y puede ser algo de lo que no estés al tanto que existe. Pero a medida que continúas investigándolo, también es parte de la cosa, parte de ello es que debes medir qué significa el éxito para ti. Ya sea el tiempo para la primera compra o cuando el usuario puede comenzar a interactuar con ella. Y eso va a ser algo que debes medir y ver qué tan beneficioso puede ser defer, porque puedes darte cuenta de que no está proporcionando el beneficio que esperas y puede que no valga la inversión continua y la inversión en ingeniería para ese caso de uso específico. Y con todo eso dicho, definitivamente creo que echar un vistazo y hacer una prueba de concepto, si aún no lo has hecho, el enrutador es una forma fácil de hacer esto a través de un modelo de Federación. Como agregar una declaración de entidad a tu servidor GraphQL existente. Esa puede ser una forma fácil de comenzar y medir si defer puede ser una buena herramienta para ti. ¿Y hay ciertas mejores prácticas o herramientas que usarías para medir o realizar pruebas de estrés para determinar qué puede ser un buen lugar para aplicar esto primero? Sí, definitivamente analizaría dónde lleva más tiempo renderizar en tu sitio. Esto puede variar según el marco de IU que estés utilizando, pero comprender dónde proviene la mayor parte de tu tiempo de renderizado generalmente puede ser donde puedes comenzar a profundizar y descubrir por qué está sucediendo esto. Y muchas veces está relacionado con tu servicio de datos. Por ejemplo, React tiene una herramienta de perfilado muy buena, que puedes usar para comprender cuánto tiempo tarda en renderizar un componente específico. Y puede ser un buen lugar para comenzar a ver cómo se está renderizando la gente o cómo se está renderizando tu datos dentro de tu IU y ver si podemos retrasar esto y renderizar parcialmente este componente hasta que obtengamos el resto de los datos. Y hablaste de problemas de rendimiento en general y algunos de esos problemas. ¿Estás viendo algún tipo de enfoques más nuevos o mejores prácticas para problemas de rendimiento además de defer que te interesen? Sí, creo que obviamente hay cosas como la directiva de transmisión que obviamente no se mencionaron en la discusión de hoy, pero creo que definitivamente vale la pena hablar de ello porque Stream también resuelve muchos de los problemas que defer puede no abordar completamente. Cosas como enviar listas completas o matrices de datos.
Enfoques Alternativos para Mejorar el Rendimiento
Defer puede no ser apropiado para todos los casos, especialmente cuando hay restricciones como los desplazamientos. Otra área interesante para explorar junto con defer es Stream. El aprovechamiento de herramientas como suscripciones o consultas en vivo también puede mejorar la capacidad de respuesta de los datos.
Este es un problema muy común en el que tienes un array gigantesco de, por ejemplo, información estadística que no deseas solicitar todo de una vez, lo cual puede ralentizar tu punto final de solicitud. Pero en este caso, defer puede no ser apropiado debido a restricciones como la capacidad de hacer desplazamientos como mencionamos durante la charla. Y por lo tanto, Stream es un área que creo que es realmente interesante y algo que también está junto con defer, por lo que una vez que se vuelva oficial será interesante seguirlo. También creo que hay otras áreas en las que puedes aprovechar las herramientas para mejorar el rendimiento. Sé que muchas personas utilizan suscripciones o consultas en vivo de manera efectiva, y esas también son utilidades buenas para ayudar con la capacidad de respuesta de los datos. Genial, excelente, muchas gracias por señalar eso. Parece que no tenemos más preguntas de la audiencia, pero ¿hay algo más que te gustaría agregar antes de tomar un descanso? Creo que lo único que agregaría es que obviamente voy a mencionar el sandbox de Apollos una vez más, así que si estás buscando integrarte con defer, creo que esta es una herramienta súper útil desde el principio, no requiere ninguna integración con las herramientas de Apollo en absoluto, solo apúntala hacia tu servidor GraphQL, y obtendrás una pequeña y bonita interfaz, pero probablemente más importante, en el contexto de defer, también obtendrás esa línea de tiempo agradable. Así puedes ver cómo ocurre tu respuesta diferida. Cosas como esta primera respuesta tarda 100 milisegundos, y luego la respuesta restante tarda tres segundos. Y puedes tener una imagen clara de cuán pronto se puede enviar esa primera respuesta para ti. Y eso es solo parte de nuestras herramientas que están disponibles de forma gratuita. Definitivamente recomiendo echar un vistazo a eso así como a defer basado en entidades de federación, porque puede ser una forma fácil de hacer esto sin ningún soporte de tu biblioteca GraphQL existente. Y si tienes alguna pregunta o algo así, no dudes en hablar conmigo en Twitter, siempre estoy feliz de ayudar. Y también creo que puse mi correo electrónico en las diapositivas. Genial, perfecto. Y solo para reiterar, ¿dónde pueden encontrarte las personas en Twitter, Lucas? Es en LLEdbetter. Mi apellido es un poco largo, pero debería estar en las diapositivas, y luego mi correo electrónico es lucas.apollo.graphql.com. Perfecto, genial. Bueno, muchas gracias por estar aquí, Lucas, y por responder nuestras preguntas y por esta charla tan interesante. Realmente apreciamos que estés aquí hoy. Sí, gracias por invitarme. ♪ Música de heavy metal ♪
Comments