Construir aplicaciones web instantáneas a gran escala ha sido elusivo. Los sitios del mundo real necesitan seguimiento, análisis y interfaces y interacciones de usuario complejas. Siempre comenzamos con las mejores intenciones pero terminamos con un sitio menos que ideal.
QwikCity es un nuevo meta-framework que te permite construir aplicaciones a gran escala con un rendimiento de inicio constante. Veremos cómo construir una aplicación QwikCity y qué la hace única. El masterclass te mostrará cómo configurar un proyecto QwikCity. Cómo funciona el enrutamiento con el diseño. La aplicación de demostración obtendrá datos y los presentará al usuario en un formulario editable. Y finalmente, cómo se puede utilizar la autenticación. Todas las partes básicas para cualquier aplicación a gran escala.
En el camino, también veremos qué hace que Qwik sea único y cómo la capacidad de reanudación permite un rendimiento de inicio constante sin importar la complejidad de la aplicación.
This workshop has been presented at JSNation 2023, check out the latest edition of this JavaScript Conference.
FAQ
Builder.io es un CMS visual sin cabeza que permite a los equipos de marketing diseñar el sitio web mediante un editor de arrastrar y soltar, sin necesidad de intervención constante del departamento de ingeniería.
Builder.io se ejecuta sobre la infraestructura existente del usuario, lo que permite registrar componentes propios y adaptar el CMS a las necesidades específicas del proyecto.
Además de Builder.io, los proyectos de código abierto asociados incluyen Quick, Party Town y Mitoses, los cuales permiten mejorar la ejecución de código de terceros y la creación de sistemas de diseño compatibles con diversos frameworks.
Quick es un proyecto que busca optimizar la cantidad de JavaScript en los sitios web para mejorar su rendimiento, basado en la idea de que menos JavaScript acelera la carga y la interactividad de las páginas.
Quick mejora los Core Web Vitals permitiendo que el JavaScript necesario se cargue de manera más eficiente y solo según sea necesario, lo cual reduce los tiempos de carga y mejora la interactividad del sitio web.
La razonabilidad en Quick se refiere a un enfoque donde el HTML se carga con la capacidad de ser interactivo de inmediato, reduciendo la cantidad de JavaScript inicial y eliminando información duplicada para acelerar la interacción del usuario.
Qwik es un framework que se enfoca en la optimización del rendimiento y la reducción de la sobrecarga de JavaScript en los sitios web. Permite la carga perezosa de componentes y la descarga y ejecución eficiente de código. Qwik se integra con varias herramientas y plataformas, incluyendo Auth.js, Superbase y headless CMS. Proporciona características como navegación del lado del cliente, cargadores de ruta y la capacidad de obtener y actualizar datos. El paradigma de renderizado de Qwik hace que cada aplicación sea instantáneamente interactiva, y React-Quickify permite el uso de componentes React existentes en aplicaciones Qwik.
1. Introducción a Quick y Optimización de rendimiento
Short description:
Hola, mi nombre es Misko y soy el CTO de builder.io. Trabajo en proyectos como Angular JS, Karma y Quick. Builder.io es un CMS visual sin cabeza que permite un editor de arrastrar y soltar. Nos enfocamos en proyectos de código abierto como Party Town y Mitoses. El mundo necesita un nuevo marco de trabajo porque los sitios web existentes tienen un rendimiento deficiente debido a la cantidad de JavaScript. Necesitamos un marco de trabajo que no abrume al navegador con JavaScript. El renderizado del lado del servidor y la razonabilidad son dos enfoques para mejorar el rendimiento al reducir la información duplicada y descargar menos JavaScript.
Hola, mi nombre es Misko. Soy el CTO de builder.io y trabajo en otros proyectos, Angular JS y Karma y ahora trabajo en un proyecto llamado Quick.
Y antes de hablarles sobre Quick, solo una pequeña descripción general rápida. Builder.io es un CMS visual sin cabeza. Básicamente, lo que te permitimos hacer es tener un editor de arrastrar y soltar para tu aplicación para que tu equipo de marketing pueda diseñar el sitio web sin molestar constantemente al departamento de ingeniería con todos los cambios que tienen que hacer. Y lo genial de esto es que se ejecuta en tu infraestructura en lugar de estar alojado en otro lugar. Como se ejecuta en tu infraestructura, puedes registrar tus propios componentes. De todos modos, aquí está su tema de código abierto. Builder tiene alrededor de 50 personas. En realidad, probablemente estamos llegando a 55 en este momento. Y nos encanta el código abierto. Y tenemos un par de proyectos además de Quick, que son Party Town y Mitoses. Party Town se utiliza para ejecutar tu código de terceros como Google Analytics dentro de web workers. Y Mitoses te permite crear sistemas de diseño, componentes existentes que tu empresa necesita. Y luego los traduce a todos los principales frameworks para que puedas tener una versión nativa de componentes de React, una versión nativa de componentes de Angular y componentes web de Quick, Salt de React, cualquier cosa que puedas imaginar. Así que este es nuestro equipo trabajando en ello. Adam Bradley solía trabajar en Ionic. Y Manuel también trabajó en Ionic y creó Gin. Y tenemos a alguien de Jabber que también trabajó en Mitoses. Así que ese es el enfoque que tenemos en el código abierto.
Y entonces la pregunta es, ¿por qué el mundo necesita un nuevo marco de trabajo? Y la respuesta a eso es, bueno, porque si miras los sitios web existentes, el rendimiento de estos sitios web no es tan bueno. Google ha invertido mucho tiempo tratando de fomentar que el mundo cree sitios web más rápidos. La forma en que lo hacen es creando algo llamado Core Web Vitals y una puntuación de Lighthouse, una puntuación de PageSpeed, y básicamente intentan mostrarte qué tan eficiente es tu sitio web. Core Web Vitals se está instrumentando en Chrome. Así que es una experiencia de usuario del mundo real. Y básicamente muestra qué tan interactivo es, ya sabes, qué tan buena es la experiencia de usuario. Y como puedes ver, la mayoría de los sitios web no tienen muy buenos números de Core Web Vitals. E incluso las empresas que se esfuerzan mucho, como Amazon, obtienen mucho, mucho mejores, pero no tienen los mejores números. Y entonces la pregunta es, ¿por qué sucede esto? ¿Sabes, por qué tenemos tantos problemas? Y lo que voy a tratar de convencerte es que realmente se reduce a la cantidad de JavaScript. Y así, cuanto más JavaScript tengas en tu sitio web, más lento se vuelve el sitio web. Y eso es algo obvio. Sabes, no es realmente tan difícil imaginar por qué sería el caso. Y entonces lo que estamos tratando de descubrir es cómo construir, quiero decir, necesitas JavaScript, ¿verdad? Porque JavaScript es lo que hace que las páginas web sean interactivas. Y si no tienes JavaScript, tus páginas no son interactivas. Entonces la pregunta es, ¿cómo diseñar sitios web para que puedas usar JavaScript para construirlos, pero al mismo tiempo no abrumar al usuario final con todo el código. O más bien, no abrumar al navegador. Y este gráfico realmente muestra que, a lo largo de los años, seguimos enviando más y más JavaScript porque esperamos más de nuestros sitios web hoy en día de lo que teníamos hace diez años. Esperamos mucha más interactividad, una experiencia de usuario mucho mejor. Y todo eso requiere JavaScript, ¿verdad? Aquí estoy diciendo que necesitamos menos, pero no en forma de, ya sabes, escribir menos JavaScript y volver diez años atrás. Eso es irrealista. En cambio, estoy diciendo, hey, sigamos escribiendo JavaScript, pero, ¿qué tal si diseñamos un marco de trabajo para que no abrume al navegador con todo este JavaScript? Entonces, en lugar de volcar todo el JavaScript de una vez al usuario, ya sabes, ¿podríamos tener un marco de trabajo donde el JavaScript aparezca según sea necesario en lugar de abrumar todo el sistema de una vez? De acuerdo. Y este es otro gráfico. Y básicamente muestra la misma información. Muestra que en el lado izquierdo, puedes ver las puntuaciones y en el lado derecho, puedes ver la cantidad de JavaScript que se está enviando. Y lo que puedes ver es que hay una relación inversa, ¿verdad? Cuanto más JavaScript enviamos, peor es el rendimiento. Y cuanto menos JavaScript enviamos, mejor es el rendimiento. Y todo se reduce a enviar menos JavaScript. Y si miras los Core Web Vitals que te da la velocidad de página de Google, es la misma historia en el sentido de que Google a menudo recomendará, hey, ya sabes, ¿puedes enviar menos JavaScript? La parte difícil es, ¿cómo exactamente haces eso? Y así que lo que estoy tratando de convencerte o más bien compartir contigo es que si miras la historia de cómo llegamos aquí, te darás cuenta de que la hidratación es un poco complicada. Esto es lo que quiero decir con eso. Primero enviamos HTML y luego originalmente teníamos una página en blanco. Y la página en blanco tenía un script dentro de ella que descargaba JavaScript que luego ejecutaba la aplicación, que luego renderizaba la aplicación y aquí es donde se mostraba tu aplicación y podías interactuar con ella. Y así que el problema es esta página en blanco. Y la gente dijo, sabes qué, realmente nos gusta el hecho de que es súper interactivo, pero esta página en blanco aquí es problemática. ¿Podemos hacer algo al respecto? Y así que crearon una aplicación en el servidor. Entonces, en el renderizado de la aplicación en el servidor, el HTML es mucho más grande, pero como resultado, en lugar de tener una página en blanco, en realidad tienes la página que ves. Y así el sitio parece más rápido, pero este sitio no es interactivo. No puedes hacer clic en él. Así que todavía tienes que descargar el JavaScript. Todavía tienes que ejecutar la aplicación y todavía tienes que renderizarla, excepto que esta vez lo vamos a llamar reconciliación porque estamos tratando de reutilizar los elementos del DOM. Y luego en este punto, en realidad tienes un sitio en el que puedes hacer clic. Y así que el renderizado en el servidor tiene esta interesante contradicción donde el sitio parece más rápido, pero en realidad es más lento para interactuar con él. Y así es la situación que tenemos. Y así que en lugar de eso, oh, sí, quiero señalar que hay mucha información duplicada. Si miras esta pila de texto construida visualmente, esta cadena se encuentra tanto dentro del HTML como dentro de JavaScript. Hay duplicación ocurriendo. Y así nos gustaría tener alguna otra forma de hacerlo. Y así que voy a omitir un par de diapositivas y te voy a mostrar qué es la razonabilidad. Entonces, la razonabilidad básicamente hace algo diferente. Comienzas con el HTML. El HTML es grande. Y como resultado, tienes la página aquí. Pero lo único único de la razonabilidad es que hay un escucha que sabe cómo interactuar con la página. Así que ya puedes interactuar con la página en este momento. Ahora todavía necesitas JavaScript. Así que la aplicación parece más rápida. Y así que comienzas a descargar el JavaScript de forma ansiosa inmediatamente cuando apareces. Pero aquí está la cosa. Observa todo este JavaScript que falta. Entonces, la cantidad de JavaScript que descargas es mucho menor. Y eso es porque la razonabilidad puede eliminar la información duplicada. Aquí tienes JavaScript para la interactividad. Pero todo esto era básicamente la información estática que ya se encuentra en el HTML. Y así, esta eliminación de duplicación significa que no tienes que volver a ejecutar la aplicación. No tienes que volver a renderizar la aplicación. Y así puedes interactuar con ella mucho, mucho más rápido. De acuerdo, creo que esta es una buena introducción. Así que voy a hacer una pausa aquí. Y luego vamos a usar esto para construir una aplicación. Pero primero, quiero ver si hay preguntas de las personas.
2. Introducción y Configuración de la Masterclass
Short description:
Tenemos a una persona de Eslovaquia. ¿Alguna pregunta o deberíamos comenzar y tratar de construir algo con Quick y ver cómo es diferente? Aquí está la URL para la masterclass. Puedes seguir el proceso y hacerme preguntas. El enlace también está disponible en la sala de chat y en el canal de Discord.
Oh, hay alguien en el chat. Ahí vamos. Es la oscuridad. Ok, así que tenemos a una persona de Eslovaquia. Genial. ¿Alguna pregunta o deberíamos comenzar y tratar de construir algo con Quick y ver cómo es diferente? Muy bien. Voy a tomar el silencio. No hay preguntas. Así que aquí está la URL. Puedo pegarla aquí en lugar de la ventana de chat. Pero también la pegué en el canal de Discord para que puedas seguir el proceso. Muy bien, todos los pasos para esta masterclass los puedes encontrar en esta URL y los vamos a revisar juntos. Puedes seguir el proceso y hacerme preguntas, etc. Alguien dice de nuevo, no estoy seguro de entender. ¿A qué te refieres con de nuevo? Oh, el enlace de nuevo. Oh, ya veo. Oh, porque solo lo envié a una persona específica. Ups, lo siento. Aquí está el enlace en la sala de chat. Y el enlace también está disponible si vas al Discord aquí.
3. Construyendo una Aplicación Quick
Short description:
Para comenzar con una aplicación Quick, ejecuta 'npm create quick at latest' y elige una aplicación vacía. Abre tu editor favorito y ejecuta 'npm run dev'. La aplicación se ejecutará en el puerto 5174. Dentro de la carpeta 'routes', crea una nueva carpeta llamada 'demo' y un archivo llamado 'index.tsx'. Define un componente y expórtalo como el predeterminado. Puedes crear un contador definiendo una variable de conteo y un botón que incremente el valor del conteo. En el modo de desarrollo, JavaScript se carga cuando interactúas con la aplicación. En el modo de producción, Quick descarga de manera anticipada todo el JavaScript necesario en la caché. La interacción con la aplicación luego carga el código en el VM de JavaScript.
OK, así que vamos a construir algo. La forma de comenzar con una aplicación Quick es, OK, asumo que el tamaño de fuente está bien. Si no es así, por favor, en el chat, señálalo y quejate, y lo corregiré. Y como dije, me encantan las preguntas. Así que haz esto más divertido para mí y pregúntame cualquier cosa que puedas tener mientras avanzamos.
OK. Así que vamos a construir una nueva aplicación Quick. Es 'npm create quick at latest'. Esto es básicamente lo que hace que tu aplicación funcione. Te pregunta dónde quieres ponerla. Llamémosla quick nation. Y en realidad hagamos una aplicación vacía que podamos construir desde el principio. Así que voy a elegir una aplicación vacía aquí. Sí, me gustaría instalar las dependencias. Y deberíamos tener esto funcionando en un segundo.
OK. Una vez que tenemos la aplicación, abramos tu editor favorito. Y aquí, siempre debemos escribir 'npm run dev'. Esto abre una aplicación. La aplicación se está ejecutando en el puerto 5174. ¿Por qué se está ejecutando en el puerto 5174? Eso simplemente significa que hay una aplicación existente que ya se está ejecutando. Abramos la aplicación. Y en realidad, hagámoslo de una forma intuitiva, y esa fuente es demasiado grande. Si la fuente no es buena, avísame. Creo que este tamaño de fuente es utilizable. OK. OK. Hemos construido una aplicación muy simple. Y aquí tienes nuestra carpeta de origen. Tienes una carpeta de rutas. Y aquí tenemos nuestro index.tsx. Y aquí es donde está nuestro texto. Hola, no puedo esperar. El texto que básicamente está aquí es lo que aparece en esta ubicación. Y este es un inicio que está vacío. Es intencionalmente tiene muy poco dentro de él. Pero así es como lo pones en marcha. Así que en este punto, básicamente hemos completado la lección 0. La lección 0 muestra básicamente cómo ponerlo en marcha. Y antes de pasar a la lección 1, quiero darte un pequeño recorrido. Así que hagamos una nueva carpeta aquí. Dentro de las rutas, hagamos una nueva carpeta, digamos demo/index.tsx. Este es nuestro enrutador. Y es un enrutamiento basado en archivos. Esto es similar a otros metaframeworks que existen, así que esto no debería ser realmente sorprendente. Creemos un componente. Y hagamos una exportación predeterminada. Así que hola desde Quix. Si vamos a la ruta demo, aquí vamos, /demo, puedes ver que el código que se muestra es básicamente este código aquí. Y si cambio esto a git nation, digamos, y guardo, nota que se recarga automáticamente. Y cuando voy aquí, puedes ver que la aplicación se ha recargado y está lista para funcionar.
Así es nuestro entorno de desarrollo en el que podemos construir nuestro sitio, construir nuestras cosas. Tenemos una recarga básica de módulos en caliente, y estoy mostrando cómo puedes usar la URL con fines de demostración. Y aquí, solo voy a mostrarte un ejemplo muy simple, y luego volveremos a la masterclass. El ejemplo que quiero mostrarte es un contador. Y lo que haces es que defines un conteo. Ahora, si estás familiarizado con React, deberías sentirte como en casa con Quick. Y es intencional que esté diseñado de esta manera. Así que creemos un conteo, y hagamos un valor de conteo, y creemos un botón. Haz clic, y ese valor, más más. ¿Y por qué no estás contento? OK, sigamos. Ahí vamos. OK, ahora tenemos un contador simple. Y, por supuesto, hacer clic en el contador incrementa el número, ¿verdad? Es una demostración muy simple. Pero lo que quiero mostrar aquí es que si voy a la pestaña de red, vamos a eliminarlo, hay dos archivos JavaScript que se cargan. Esto es vit, vit para la recarga de módulos en caliente, etc. Esto solo está en modo de desarrollo, y no está en producción. Voy a escribir para eliminar el vit. Y una vez que elimine el vit, aquí es donde vemos la diferencia de cómo funciona realmente Quick. Así que en Quick, no hay JavaScript. No ha aparecido nada. Y es cuando interactúo con la aplicación que aparece JavaScript. Ahora sé lo que podrías estar pensando, como, bueno, eso está bien, pero ¿eso no significa que cada vez que quiero interactuar con ella, tengo que hacer una solicitud del lado del servidor y, como resultado, será lento? Esto es en modo de desarrollo. Así es como funciona en desarrollo. En modo de producción, funciona de manera un poco diferente. Permíteme mostrarte cómo es diferente en producción. Antes de ir a cualquier parte, quiero ir a la carpeta de la aplicación y mostrarte que la caché está vacía y no hay un service worker. Vamos a un sitio web construido con Quick. Vamos a nuestra página de inicio de Quick. Y nota que tan pronto como navego a la página de inicio, la caché se llena con el JavaScript apropiado. Entonces, lo que es único al respecto, como el service worker tiene un service worker aquí que sabe cómo ir y buscar todo esto. Entonces, lo que es único es que en producción, Quick descargará de manera anticipada todo el JavaScript que podrías necesitar para esta interacción. Pero no lo descarga en el VM, en la máquina virtual, en el VM de JavaScript. Solo lo coloca en la caché. Y solo cuando interactúas con la aplicación, solo entonces el código aparece dentro del VM de JavaScript. Permíteme mostrarte, vamos a la pestaña de red, vamos a borrar esto. Y cuando interactúo con algo, como por ejemplo aquí, nota que aparece JavaScript.
4. Construyendo la Ruta de GitHub y Obtención de Datos
Short description:
Pero ten en cuenta que dice service worker, fue el que respondió, no el código real. Con otros frameworks, tendrías que descargar todo el componente, y no solo este componente, todo lo de arriba. Quick sabe cómo dividir tu aplicación en piezas y luego enviar solo el código relevante al cliente según sea necesario. Las aplicaciones Quick tienen esta propiedad interesante de que siempre comienzan prácticamente sin ejecución, y luego, a medida que interactúas con ellas, se carga el código relevante en la máquina virtual y comienza a ejecutarse. Vamos a construir aplicaciones. Construyamos una ruta que pueda obtener una lista de URLs de GitHub. Extraemos el usuario de nuestra URL y queremos hacer esto en un servidor porque no queremos enviar un token de acceso de GitHub al cliente porque es un token privado que no queremos compartir con nadie.
Pero ten en cuenta que dice service worker, fue el que respondió, no el código real. Y como resultado, siempre es interactivo, incluso si la red se ha caído, etc.
De acuerdo, volvamos aquí. Cuando presiono más uno, aparece la red. Ahora, lo único único aquí es que, luego, fíjate qué código apareció. Observa que el único código que apareció es el código que está aquí dentro. Ese es el único código que está aquí. Hay algo adicional al principio para recuperar el estado del conteo. Obviamente, el framework aparece, y este es un archivo de construcción que se, se elimina en producción, así que puedes ignorarlo. Pero esto es interesante porque así es como funcionan otros frameworks. Con otros frameworks, tendrías que descargar todo el componente, y no solo este componente, todo lo de arriba. Entonces, realmente comenzarías con el componente raíz y descargarías recursivamente todos los componentes que necesitas. Y luego, la hidratación requiere que todo el código se ejecute. Y déjame mostrarte que el código no se ejecuta aquí. Entonces, si digo, render counter, y guardo, observa que en un servidor se ejecuta esa función. Porque el servidor necesita renderizar este componente en particular. Y así que el servidor definitivamente tiene que ejecutarlo. Pero si vas al cliente, incluso si interactúo con la página, sabes, la aplicación está funcionando, observa lo que falta aquí. Que esta función nunca se vuelve a ejecutar. No solo que no se vuelve a ejecutar, en realidad, ni siquiera se descarga. Como no se encuentra en ninguno de los códigos que se están descargando. Y esto es lo que es único acerca de Quick, que Quick sabe cómo dividir tu aplicación en piezas y luego enviar solo el código relevante al cliente según sea necesario. Y nuevamente, te estoy mostrando el modo de desarrollo y en el modo de desarrollo, este es el caso extremo. En producción, en realidad obtienes múltiples símbolos dentro de un solo archivo. Por cierto, lo que sea que esté detrás del signo de dólar, llamamos a esto un símbolo. Entonces, ahora mismo, tienes un símbolo por archivo, en el modo de producción tendrías múltiples símbolos por archivo, por lo que el comportamiento es ligeramente diferente en producción, pero tienes la idea de que lo interesante es que JavaScript no tiene que ejecutarse hasta que lo interrumpas. Y aunque esta es una aplicación trivial, el hecho de que no haya JavaScript presente también significa que no se ejecuta JavaScript, ¿verdad? Entonces, las aplicaciones Quick tienen esta propiedad interesante de que siempre comienzan prácticamente sin ejecución, y luego, a medida que interactúas con ellas, se carga el código relevante en la máquina virtual y comienza a ejecutarse. De acuerdo, eso es una descripción general rápida, y luego vamos a construir aplicaciones. ¿Alguna pregunta? Como dije, me encantan las preguntas. Realmente haces esto mucho más interesante para mí y para todos los demás si haces preguntas, así que te animo mucho a que preguntes, me interrumpas en cualquier momento. Creo que es genial. De acuerdo, así que deshagámonos de la demo, y vayamos a nuestra primera lección. Entonces, lo que nos gustaría construir es construir una ruta que pueda obtener una lista de URLs de GitHub. Así que creemos un nuevo archivo, y así que fíjate en este caso particular, el directorio es github / usuario / index, ¿verdad? Y así que nuevamente, voy a tener que crear un componente. Tiene que ser una exportación predeterminada, y ahora dice hola, quick, así que ahora podemos ir a github / mhebrey, ¿verdad? Y así que lo que pongo aquí podría ser cualquier cosa. No importa lo que ponga aquí porque esto es un catch-all, ¿verdad? Así que estoy extrayendo este parámetro. De hecho, podemos obtener ese valor y podemos decir const location, use location, y luego podemos decir, podemos decir location, RAMs, ahora dice usuario, así que voy a decir usuario aquí, ¿verdad? Entonces, ahora, si voy a visitar, dice hola mhebrey. Si cambio esto a builder.IO, dice lo que sea el valor particular. Y así que lo que nos gustaría hacer es en realidad ir y hablar con un GitHub para obtener una lista de repositorios para este nombre de usuario. Y para facilitar eso, voy a obtener información de tipo. Entonces, este es un proyecto que tiene toda la información de tipo para hablar con GitHub, así que voy a instalar esto. Y voy a hacer trampa un poco y simplemente copiar y pegar este código. Y voy a explicar este código en un segundo. Así que peguemos este código aquí. De acuerdo, entonces lo que hace este código, y tienes que importar tu cargador de rutas. Por alguna razón, TypeScript ha caído. TypeScript reinicia el servidor TS. Dame un segundo. No, ¿por qué no se importa automáticamente? Vamos, TypeScript. Déjame salir. De acuerdo, ¿qué hacemos aquí? Entonces, primero que nada, instalamos el OctoKit open API. Y así que ahora podemos importar los tipos desde los tipos de la API abierta. Y solo voy a extraer un tipo específico llamado organization repos response. Entonces, esta será la respuesta que obtendremos de GitHub cuando busquemos una organización específica o un nombre de usuario específico. Y lo siguiente que debemos hacer es ir y obtener los data de esta URL. Entonces, esta es la URL que proporciona GitHub y puedes hablar con ella. Y para obtener los data, GitHub quiere un agente de usuario, una versión y un token de acceso de GitHub. Entonces, puedes obtener un token de acceso de GitHub yendo a GitHub, yendo a tu nombre de usuario. Entonces, si vas a GitHub, voy a cada uno, vas aquí, configuración, vas, creo que a configuración local. Y así que desde aquí, puedes obtener un token de acceso personal. Creo que es este. Así que ya lo he hecho. Así que voy a hacer trampa un poco. Así que si copio aquí, Veamos si puedo... Entonces hay un archivo de entorno. Y este archivo de entorno básicamente muestra, Este archivo de entorno básicamente muestra todos los tokens que vas a necesitar a medida que construyas este proyecto. Entonces, ahora mismo necesitamos este token de acceso de GitHub. Y así que ya lo he hecho, así que voy a copiarlo. Y, sabes, para mí, he creado un nuevo archivo, entorno local, y no lo voy a mostrar porque en realidad tiene mis tokens de acceso y no quiero tener que rotarlos todo el tiempo. Pero este archivo de entorno, no quiero tener que rotarlos todo el tiempo, pero este entorno local es básicamente el mismo archivo exacto que este archivo, excepto que los valores aquí son los tokens reales. Oh, vamos ahora. Lo siento, estoy luchando con Zoom aquí por un segundo. Oh, por Dios. Entonces, aquí podemos obtener el token. Entonces, esta función route loaders, bueno, ¿qué estamos tratando de lograr? Lo que estamos tratando de lograr es obtener una lista de todos los repositorios para esta URL en particular. Y así que extraemos el usuario de nuestra URL, ¿verdad? Y queremos hacer esto en un servidor porque no queremos enviar un token de acceso de GitHub al cliente porque es un token privado que no queremos compartir con nadie, ¿verdad? Y así que este fragmento de código debe ejecutarse en un servidor. Y así que para eso, tenemos esta función llamada route loader. Y así que el trabajo de route loader es básicamente decir, Oye, alguien navega a la URL de GitHub slash algo, necesito que vayas y obtengas estos data de GitHub y hagas que este data esté disponible dentro de los repositorios del usuario. ¿Verdad? Y así que debido a eso, podemos obtener los repositorios aquí. Repositorios, cierre estos repositorios. Para decir, Oye, alguien navega a tu URL de GitHub slash algo, necesito que vayas y obtengas estos data de GitHub y hagas que este data esté disponible dentro de los repositorios del usuario. ¿Verdad? Entonces, esto básicamente se asegura de que no estemos yendo a ningún servicio para administrar los data que quedan en la superficie. Si hacemos esto, en realidad se ejecutará. Podemos hacer esto se ejecutará si alguien va y y podemos hacer esto se ejecutará si alguien va y y puedes hacer esto se ejecutará. y así que eso es una recompensa. Y simplemente devolvamos json. stringify. paréntesis. Aquí vamos. De acuerdo, así que ahora si voy a mi página.
5. Usando Quick y Serialización
Short description:
Creamos una ruta que obtiene datos del repositorio de GitHub usando un token de acceso privado. Los datos obtenidos se utilizan en el método useRepositories. Al filtrar el conjunto de datos, el sistema reconoce la necesidad de serialización al interactuar con los datos. El signo de dólar en Quick garantiza la carga diferida de funciones y la capacidad de serializar varios tipos de datos. Sin embargo, hay casos en los que Quick no puede serializar ciertos tipos, lo que resulta en un error.
Oh, disculpa, debes ejecutar un servidor y NPM. ¡Ups, NPM run. Ahora, si ejecuto, puedes ver que tengo una lista de mis repositorios y creo que puedo pedirle que me envíe más. De acuerdo, para la página 100. Ahora tengo 100 de mis repositorios que el servidor ha devuelto.
Ahora, obviamente, esa no es la forma en que quieres mostrar los datos al usuario, pero quiero revisar lo que hemos hecho. Así que creamos una ruta que tiene una clave particular dentro de ella. Llamamos a esto Prem y luego usamos este Prem para construir una URL en la que hablamos en el servidor. Entonces, este fragmento de código nunca llega al cliente. Usamos este fragmento de código para ir y obtener un conjunto de datos del repositorio de GitHub. El repositorio de GitHub requiere un token de acceso privado. Entonces, obtenemos el token de acceso privado. Lo establecemos aquí, y este token de acceso privado proviene del entorno del servidor. Este entorno es un entorno de servidor. Y luego, lo que obtenemos es useRepositories.
Y nuevamente, si eres un usuario de React, sabes cómo usar el método use. Y así puedes usar el método use para obtener este objeto. Si eres un usuario de React/Next.js, entonces lo que hemos hecho aquí es esencialmente obtener props estáticos. Pero esto es un poco mejor que obtener props estáticos por un par de razones. En primer lugar, puedes tener tantos cargadores de rutas como desees. Te mostraré cómo crear más en el futuro. Mientras que solo puedes tener un getStaticProps por archivo. Y la otra diferencia es que en getStaticProps, no se te permite hacer referencia a getStaticProps porque quieres que el framework lo llame en un servidor, pero quieres asegurarte de que ese método, la función, se elimine en el cliente. Y para que la función se elimine en el cliente, el getServerProps no puede hacer referencia a ella. De lo contrario, rompes la eliminación de código, ¿verdad? Entonces, la forma en que funciona es que este es un experto bien conocido en Next.js, y como es un experto bien conocido, y debe llamarse getStaticProps, Next.js sabe cómo llamarlo. Y aquí, eres libre de llamarlo como quieras. Y la ventaja de esto es que si pasas el cursor sobre él, verás que la información de tipo fluye correctamente. Entonces, nuestros repositorios ya tienen una información de tipo correcta que fluye hacia el cliente. Veamos, ¿hay preguntas? No veo nada en el chat, ¿y está el otro chat? Revisa este, de acuerdo, no veo nada en este chat tampoco.
Así que hagamos que esto se vea más bonito. En lugar de simplemente hacer un JSON.stringify en un repo, probablemente quieras hacer un LI. El LI necesita una clave, así que hagamos key es repo.id, ¿creo? Ahí vamos. Y hagamos repo.fullname. Y así ahora, obtenemos una lista de todos mis repositorios para mí. Y puedo cambiar esto, puedo ir a builder.io, y obtendré todos los repositorios para el otro usuario ahora. Nuevamente, volviendo aquí, observa si vas a la pestaña de Red, no se está descargando ningún JavaScript. Y eso se debe a que no hay interactividad aquí, ¿verdad? Porque no hay interactividad, ya sabes, el sistema lo mira y dice, sí, no hay necesidad de JavaScript, pero incluso si hubiera interactividad, el sistema es bastante inteligente para descargarlo.
Ahora, lo otro que debemos tener en cuenta es que hay Quick JSON. Y esto es algo así como el estado del sistema. Y esto es algo así como el equivalente a la etiqueta de script de datos de Next que existe en Next.js, si estás familiarizado con ese sistema. Y en este caso particular, el sistema lo miró y dijo, sí, no hay nada que serializar. Y eso se debe a que no puedes volver a renderizar ningún código en el cliente, por lo que aunque todos estos datos provienen de un servidor, no están aquí porque, bueno, no hay realmente nada que puedas hacer con ellos. Entonces, simplifiquemos esto un poco, o más bien agreguemos algo de interactividad. Entonces digamos, filter igual a use signal, por lo que use signal es algo así como use state, por lo que decimos que no tenemos ninguna señal al principio y podemos hacer tipos de entrada. De acuerdo, está bastante cerca, así que hagamos value, input dollar, filter, value equals, oops, va a ser una función de devolución de llamada, y así que va a tener un evento y un objetivo, así que es target.value, ¿verdad? Así que ahora estamos diciendo que cada vez que escribamos en el campo de entrada, nos gustaría actualizarlo, y para mostrar que se está actualizando, filter.value, simplemente imprimiremos este filter.value, y así que ahora tenemos nuestra lista de respuestas, tenemos nuestra entrada y podemos escribir aquí, y a medida que escribo aquí, podemos ver que el valor se actualiza. Así que tenemos enlace. Pero lo que nos gustaría hacer es usar esa información para filtrar los repositorios. Entonces, una forma de hacerlo sería decir filter, y filter toma un repo. Entonces, repo.fullname2 en minúsculas incluye filter value en minúsculas. De acuerdo, así que ahora estamos diciendo, oye, antes de renderizar todo, solo muestra los que tienen todo esto. Así que ahora mismo tenemos todo y tal vez solo escribo click y de alguna manera solo tengo click. Y así es interactivo, a medida que escribo, los datos se actualizan. Y quiero señalar un par de diferencias aquí, solo al filtrar un conjunto de datos, de repente el sistema reconoció, oye, ¿sabes qué? Necesito serializar los datos que provienen del servidor porque existe la posibilidad de que los vuelva a renderizar en el cliente, ¿verdad? Observa, si solo comento el filtrado, el sistema se da cuenta, oh, no hay forma de interactuar con estos datos. Y por lo tanto, estos datos ya no se serializan. Así que puedo escribir aquí, es interactivo, pero no se está realizando ninguna serialización, ¿verdad? Nuevamente, veamos la pestaña de Red. El único código que se descarga es el código para el primer valor y nada más. Y así que siempre es agradable señalar que no solo el sistema y elimina correctamente el código innecesario, sino que el sistema también elimina los datos innecesarios. Entonces, solo se serializan los datos que realmente se necesitan. De acuerdo. ¿Alguna pregunta hasta ahora, o estamos bien? Tal vez un pulgar hacia arriba. De acuerdo. Sigamos adelante. ¿Está el chat, puedes ver mi chat o está oculto? Porque creo que está, solo me preocupa bloquear la demostración que estoy mostrando. Espero que la ventana de chat no sea algo que veas en tu lado. ¿Qué sucede si los datos no se pueden serializar a JSON? Ah, excelente pregunta. Entonces, Quick, hablemos del signo de dólar por un momento. Observa que hay estos signos de dólar aquí, y aquí. Y lo que hacen estos signos de dólar, es asegurarse de que, lo que sea que esté detrás de ellos, típicamente una función, esa función se pueda cargar de forma diferida. Así que puedes pensar en esto como carga diferida. Ahora, nuevamente, hay un prefetcher para que, ya sabes, no haya latencia de red cuando haces eso. Y así que la pregunta es, está bien, pero si cargo de forma diferida una función, la función tiene un estado en el que se cierra. Entonces, en este caso, estás cerrando sobre el filtro, ¿verdad? Lo que significa que estás cerrando sobre los valores. Entonces, la regla del signo de dólar es que, lo que cierra, como el valor del filtro, debe poder serializarse. Y una señal definitivamente no es algo que JSON sepa cómo serializar, pero Quick sí. Entonces, en realidad puedes serializar muchos tipos diferentes. Ciertamente puedes serializar señales, lo siento, señales. Puedes serializar cosas como fechas, conjuntos, mapas, errores, promesas. Hay muchos tipos diferentes que Quick simplemente sabe cómo serializar sin que tengas que preocuparte. Pero tienes razón, siempre hay un tipo que Quick no podrá serializar. Y en ese caso, obtendrás un error. Permíteme mostrarte un ejemplo de eso. Entonces, digamos que queremos imprimir, hagamos una constante objeto igual a, solo voy a crear una clase. Oops, ah. Creo que puedo simplemente decir new aquí. De acuerdo. De acuerdo. Um, de acuerdo. Entonces aquí está el objeto y tratemos de, así que actualicemos esto. Para que cada vez que, en realidad, hagamos un nuevo botón para que sea más sencillo. Hagamos un nuevo botón.
6. Serialización en Quick
Short description:
Quick puede serializar muchas cosas, pero no todo. Si es algo que no se puede serializar, generalmente Quick te lo indica. Cosas como streams, clases, debes recrearlas en el cliente porque no son serializables.
Y al hacer clic, y aquí, cada vez que hago clic en él, diré console log object to string, ¿verdad? Así que ahora estoy intentando serializar el objeto. Y como el objeto es una clase, no es serializable. Y así que observa que incluso el sistema de tipos ya está ayudando, ¿verdad? Y está diciendo, Oye, parece que estás haciendo referencia a un objeto dentro de un ámbito diferente, en este caso, en el clic. De acuerdo. Esto es mi forma. Acabo de escribir esto cuando esto sucede, Quick necesita serializar el valor, ¿verdad? Así que esta es una de las reglas del lado del poder que debe ser serializable. Sin embargo, en esta instancia, la clase no es serializable. Así que sabes, te está señalando las reglas y debes hacer algo de lectura, pero también cuando ejecutas esto, puedes ver que estás intentando hacer es intentar serializarlo. Y esto es algo que no es serializable. Hay formas de solucionarlo. Una de ellas es no serializar, básicamente le dices al sistema, como no te molestes en serializar, pero luego depende de ti en el código de tu aplicación lidiar con ello. Básicamente obtienes indefinido en el otro lado y luego tienes que recrearlo o lidiar con ello, etc. Entonces, la respuesta corta es Quick puede serializar muchas cosas, pero no todo. Y si es algo que no se puede serializar, generalmente Quick te lo indica. Y, sabes, básicamente depende de ti lidiar con este problema en particular, ¿verdad? Entonces, cosas como streams, clases, ya sabes, esas debes recrearlas en el cliente porque, ya sabes, no son realmente serializables. Espero que eso responda la pregunta.
7. Serialización, Estilización e Integración
Short description:
Te mostré cómo funciona la serialización y cómo estilizar componentes en Quick. La carga perezosa es una característica clave que permite la descarga y ejecución eficiente de código. El sistema serializa automáticamente los datos relevantes y solo descarga los componentes necesarios. El renderizado en el lado del servidor permite una página interactiva sin JavaScript. El formato JSON de Quick garantiza una serialización eficiente de datos. También mencioné la integración de la biblioteca Auth.js.
Bien, veamos. De acuerdo. Así que veamos, de acuerdo. Lo que realmente quería mostrarte es cómo funciona la serialización. Entonces, si vas a la red, oh, perdón, si vas a los elementos, puedes ver que en este caso, lo que estamos serializando es realmente solo, solo el valor inicial aquí. Pero si descomentamos el filtrado, entonces el framework se da cuenta, oh, ahora tengo que serializar el estado completo que vino del servidor porque es posible que interactúes con estos datos. Entonces, al escribir quick, tengo que volver a renderizar el componente y como resultado, necesito tener los datos completos del servidor. Y lo que se serializa se expande automáticamente aquí.
Bien, veamos. De acuerdo, déjame mostrarte el estilizado. Así que creemos un estilo para este componente porque el componente no se ve muy bien. No soy un experto en estilizado. Espero que tengas a alguien en tu equipo que lo sea, pero déjame mostrarte cómo se hace el estilizado. Así que creemos index.css. Peguemos algunos estilos para este componente en particular, como tenemos card list y card item. Y... Y aquí están las clases... Y... Ahora, esto en realidad no iniciará nada todavía porque creamos la hoja de estilos, pero no la hemos cargado. Entonces lo que necesitamos hacer es importarla. Y como este es un entorno de beat, beat básicamente tiene algo especial llamado interrogante en línea, que le dice a beat que quiero el contenido del archivo en lugar del archivo para ser insertado automáticamente en la cabeza de la aplicación. Y así, obteniendo el contenido, podemos cargarlo diciendo use styled scoped. Y esto sabe cómo aplicarle un alcance para que si tienes CSS ahí dentro que entra en conflicto con otros componentes, se aplique correctamente para evitar conflictos. Ahora, si subo aquí, puedes ver que mis repositorios están estilizados, es decir, se ven correctamente. Y si vas a uno de ellos, verás que se inserta una clase especial que es única y no se encuentra en ningún otro lugar. Y el estilo se insertó en esta ubicación y puedes ver que el estilo también se reescribe con la información correcta. Así es como funciona el estilizado. Pero quería mostrarte una cosa más. En realidad me lo salté. En este caso, estamos volviendo a ejecutar este código, lo que está causando que se vuelva a ejecutar el filtro. Hay otra forma de hacer esto y se llama computed. Así que podemos decir const filtered repositories. Y en React, simplemente pondrías el código aquí directamente. Pero como queremos hacer toda esta carga perezosa mágica, tenemos que hacer algo llamado use computed. Y use computed es la forma de calcular nuevos valores. Así que hagámoslo aquí. Lo que queremos es, veamos. Sí, creo que ese es el código correcto. Básicamente estamos diciendo, oye, los repositorios filtrados son iguales a, iguales a, ya sabes, los repositorios regulares, pero tienes que ejecutar y ejecutar este código en ellos. Así que tienes que filtrarlos. Y luego aquí, en lugar de hablar de repositorios, vamos a decir repositorios filtrados, y podemos eliminar esta parte aquí. Y observa que debido a que el sistema utiliza señales, sabe que debe volver a ejecutar esta parte de código cada vez que cambia el filtro. Entonces, cada vez que el filtro cambia, volvemos a ejecutar esta parte de código, y luego, como resultado, podemos volver a ejecutar la plantilla. Permíteme mostrarte esto de nuevo. Ve a la pestaña de red. Si escribo aquí algo, lo primero que se descarga es el listener para el input, ¿verdad? Eso es, ¿dónde está el input? Ahí está este código. Después de eso, descargamos el framework. Y luego lo siguiente que tenemos que descargar es el computed. Debido a que hemos cambiado el valor del filtro, tenemos que volver a ejecutar esta función aquí para actualizar los repositorios filtrados. ¿Correcto? Así que esto, puedes ver que es el código asociado a ese código para actualizar los repositorios. La siguiente parte, ¿qué descargamos a continuación? Entonces, lo siguiente que descargamos es, descargamos el componente en sí. Así que ahora tenemos que volver a ejecutar este código aquí para actualizar la interfaz de usuario. Y puedes ver que esa parte de código se descarga a continuación y se vuelve a ejecutar y, veamos, ¿qué es esto? Oh, bueno, esto es, oh, esto es, porque los datos provienen de un cargador de rutas, hay cierta lógica que debe ejecutarse para asegurarse de que los datos no hayan cambiado en el servidor. De todos modos, ahora que básicamente podemos y lo otro que hay que señalar, ¿verdad?, es que en producción, en lugar de tener una cascada que sucede aquí, en producción, las partes de eso se colocarían juntas. Ahora, en este caso, solo tenemos un componente aquí, y así forzamos a descargar todo el componente, pero en la aplicación real, tendrías muchos, muchos más componentes, y la mayoría de ellos serían estáticos. La mayoría de ellos no se volverían a renderizar, y así obtienes muchos beneficios al tener un sistema que carga perezosamente todo en partes como esa. Permíteme mostrarte una cosa más en este caso en particular, y eso es, este patrón aquí, como enlazar el valor de los datos, y luego simplemente escuchar el input, es tan común que en realidad puedes decir esto. Y eso es absolutamente equivalente a, ¿qué es, qué? String o Undefined, ¿por qué es Undefined? Oh, es posible que el tipo de input sea Undefined. ¿Qué? De acuerdo, eso es interesante. Algo que arreglar. Solo deshacerlo para que no tengamos un error de tipo. De todos modos, ambos son esencialmente equivalentes. Oh, oh, sé por qué es un error, lo siento. Es mi culpa. Es porque tienes que hacer filter. Aquí vamos. Aquí vamos, de acuerdo. De acuerdo, todo funciona. El ID de inicio de sesión ha vuelto. Todo funciona como debería. De acuerdo, en esto, básicamente es exactamente lo mismo que esta parte, y así, puedes ver que es completamente interactivo, etcétera. Avísame si tienes alguna pregunta, de lo contrario, pasemos a la siguiente parte de la lección. De acuerdo. De acuerdo. Así que intentemos ahora obtener un código de autenticación en la aplicación. Hay una biblioteca muy popular llamada Auth.js. Así que vamos a instalarla. Una de las cosas que quiero mostrarte es que Quick tiene muchas integraciones.
8. Integraciones de Quick
Short description:
Quick ofrece una amplia gama de integraciones, incluyendo implementación en plataformas principales como Cloudflare, Azure, Netlify y más. También se integra con AddLess CMS, Cypress, Storybook, Auth.js, Playwright, PostCSS, Prisma, Style.DNA extract, Tailwind, VTest y Partytown. Además, Quick permite el uso de componentes de React, aunque sin la carga perezosa y otras características proporcionadas por Quick.
En este caso particular, Quick está preguntando, ¿qué integración quieres agregar? Y observa que tenemos muchas integraciones. Básicamente podemos implementar en todas las plataformas principales, Cloudflare, Azure, Netlify, Bursell, Google Cloud, ejecutar Deno, Express, Fastly, incluso HTML estático en Apache, AWS, Lambda. Ya hay una solicitud de extracción, y creo que incluso se ha fusionado, pero aún no hemos lanzado, solo tenemos que lanzar la última CLI. También tenemos muchas integraciones con cosas como, AddLess CMS, Cypress para pruebas, Storybook para pruebas. Aquí está el Auth.js, en el que vamos a profundizar. Tenemos Playwright, PostCSS, Prisma para ORM de base de datos, Style.DNA extract, que es similar a Emotion, Tailwind, que es popular, VTest, y por supuesto el Partytown para ejecutar tu código en lugar de terceros. Y finalmente, en realidad tenemos una integración con React en el sentido de que puedes usar componentes de React dentro de Quik. Por supuesto, no obtendrás toda esta magia de carga perezosa y utilización, y todas estas cosas que Quik muestra, pero muestra que React es algo que puedes usar dentro de Quik.
9. Instalación de Auth.js y Configuración de Autenticación
Short description:
Queremos instalar Auth.js, lo cual requiere un truco en las configuraciones profundas debido a la creación incorrecta de archivos ESM. Se deben configurar variables de entorno para la API y la clave secreta de GitHub, así como una clave de autenticación privada. El archivo plugin.auth se utiliza para la configuración, incluyendo el uso de GitHub y otros proveedores. El método use permite cargar repositorios y verificar el estado de inicio de sesión. El archivo layout TSX se puede modificar para incluir un botón de inicio de sesión, que invoca la acción de cierre de sesión. El uso de la sesión de autenticación se puede utilizar para mostrar información del usuario de forma condicional. Quick recomienda proporcionar altura y ancho para las imágenes para evitar cambios en el diseño.
Entonces, lo que queremos es instalar Auth.js. Así que simplemente marquémoslo. Mientras se descarga, tenemos que hacer un pequeño truco. Resulta que Auth.js no crea correctamente los archivos ESM, por lo que tenemos que hacer un pequeño truco en las configuraciones profundas para que no intente agrupar esto como Auth.js. Esperemos que el paquete de Auth.js se corrija en el futuro, y entonces no tendrás que hacer esta parte en particular.
De acuerdo, así que vamos a tener que crear una variable de entorno. Si vas a EMP de nuevo, vamos a tener que configurar una API y una clave secreta de GitHub y la clave de autenticación privada, que es solo un valor aleatorio que se utiliza para crear hashes, y puedes crearlos con un valor aleatorio de esta manera en particular. De nuevo, ya he hecho esto antes. Así que ahora que tenemos esto, tenemos vtauth. Oh, sí, cuando ejecutamos la línea de comandos, se creó este archivo especial llamado plugin.auth. Y, entonces, plugin.auth es, se ve así, y aquí es donde configuras todas las piezas. Creo que, si recuerdo correctamente, los nombres son en realidad diferentes. Creo que agregué la palabra private aquí, private aquí y también aquí. Entonces, en este caso particular, me gusta agregar el prefijo con la palabra private para que quede claro que, ya sabes, esto no está destinado a llegar nunca al cliente. Y así, si llega al cliente, sería un problema. Y esto es una especie de configuración para el servicio de autenticación. Puedes ver que hemos configurado un GitHub, pero también podemos configurar otros. Y observa que tenemos un método use de la misma manera que teníamos un método de ruta. Solo regresemos aquí. Mira cómo tenemos un cargador de ruta que sabe cómo cargar los repositorios. La autenticación también tiene un cargador que sabe cómo decirte si estás actualmente conectado o no. Y lo bueno de esto es que puedes declarar este método use en cualquier ruta, y luego puedes usarlo en cualquier lugar dentro de tu componente que esté en esa ruta en particular. Entonces, nuevamente, la diferencia con getStaticProps es que getStaticProps debe declararse en el mismo archivo que todo lo demás. Y obtienes el valor de getStaticProps dentro de las props de tu componente. Y así, si lo necesitas en algún lugar profundo, tienes que ser adecuado, no está automáticamente disponible. Y así, lo bueno del método use es que, bueno, puedes usarlo en cualquier lugar que desees. De acuerdo, aquí lo configuramos. Y lo que obtenemos son los onRequests, que es una función middleware que configura automáticamente las cookies, etc., y ya está proporcionada, así que no tienes que preocuparte por eso. Y obtenemos estos métodos de uso, que muestran tanto un cargador, que te dice si estás actualmente conectado o no, y te proporciona dos acciones para iniciar sesión y cerrar sesión. Y así, usemos estas tres piezas para mostrarte cómo funcionarían todas estas cosas. Primero, probablemente querremos ir al archivo layout TSX, y el archivo layout TSX actualmente solo dice div. Pero probablemente dirá algo como esto. Entonces, el slot es donde se proyecta el contenido. ¿Por qué no estás contento, div? Oh, porque lo hice así. De acuerdo, aquí es donde probablemente dirías header, y solo dirías header aquí. Header. Y luego aquí dirías footer. Construido con mucho amor, algo así. Entonces es punto y coma, de acuerdo. Y así, este diseño se convertirá automáticamente, observa, si actualizo, oh, el servidor no se está ejecutando. Así que actualizaré el servidor, npm run-dev. De acuerdo, ahora esta página debería actualizarse, y observa que hay un encabezado y hay un pie de página que se incluye. Y como es un diseño, este archivo en particular se incluirá en todas partes. Entonces, lo que debemos hacer aquí dentro del encabezado es básicamente decir, oye, me gustaría tener un botón de inicio de sesión. Entonces probablemente será un botón. De acuerdo. De acuerdo, hay un botón de inicio de sesión que me gustaría. Y así, como puedes ver ahora, en la parte superior hay un botón de inicio de sesión aquí. Y así, lo que queremos hacer es invocar esta acción, la acción de cierre de sesión aquí. Así que volvamos al diseño. Y así, digamos const sign-in-action, esta cosa, obtenemos esto, tenemos que importarlo. Y así, lo siguiente que debemos hacer es obtener un formulario porque es un botón y será un envío. Así que obtenemos el formulario. Observa que este es un formulario en mayúsculas. Y así, aquí dentro, ahora podemos ir a hablar con la acción de inicio de sesión. Así, y tenemos que importar esto. De acuerdo, ahora tenemos un botón en el que podemos hacer clic. Así que probemos esto. Si hago clic en iniciar sesión, me lleva a una página, la página del proveedor de autenticación donde GitHub ya está configurado. Puedo hacer clic en iniciar sesión, veamos si puedo recordar el nombre de usuario y la contraseña. Ya sabes. De acuerdo, ahora estamos siendo redirigidos de nuevo a nuestra página y hemos iniciado sesión, pero aún dice iniciar sesión. Entonces probablemente queremos mostrar un botón diferente, ¿verdad? Probablemente queremos mostrar esto condicionalmente dependiendo de lo que esté sucediendo. Así que recordemos que esta autenticación también proporcionó un uso de sesión de autenticación. Y así, este es el tipo de enlace. Enlace. De acuerdo, obtengamos la sesión de autenticación. Así que digamos const auth, auth user equals user así. Y así ahora queremos decir aquí es como, bueno, si user.value.name no, eso no es correcto. Oh, lo siento, tenemos que importar, por eso el sistema de tipos no está funcionando. Importar esto, de acuerdo. Entonces, si tenemos un usuario, ¿verdad? Entonces queremos hacer, bueno, queremos decir mostrar usuario. De lo contrario, queremos hacer este formulario o iniciar sesión, ¿verdad? Y así ahora dirá mostrar usuario, pero como realmente queremos imprimir los usuarios. Vamos a tomar esto de nuevo. Y así queremos hacer algo como, mostrar usuario. Hagamos un correo electrónico, un buen nombre, en realidad. Y así ahora dice mi nombre. Y nos gustaría mostrar una, imagen para mí. Así que hagamos imagen. Eso es correcto ahora usuario, imagen de usuario. Así que ahora muestra la imagen, pero observa lo que sucede. Quick se queja y dice, oye, por razones de performance, siempre debes proporcionar altura y ancho porque si no lo haces, tendrás un cambio de diseño acumulativo aquí. Correcto. Entonces, cuando se carga la página por primera vez, no hay imagen. Y así, la Mishka tiene razón en la primera línea, y luego cuando se carga la página, no parpadea en el contenido fijo. Y así básicamente te está diciendo, por favor, ¿podrías proporcionar altura y ancho? Es 25, 25 y ahora esto está bien.
10. Visualización y Estilización Condicional de Imágenes con CSS
Short description:
Mostramos condicionalmente la imagen y el nombre de usuario, y estilizamos el diseño con CSS. El componente slot en Quix permite la proyección de hijos de manera declarativa. Esto evita volver a ejecutar componentes y minimiza la cantidad de JavaScript descargado. RouteAction es una acción realizada en el cliente que ejecuta código en el servidor, similar al paradigma de publicación HTTP.
¿Cuál es el problema aquí? Ah, sí. Es posible que no haya una imagen. Creo que lo que debemos hacer es mostrar condicionalmente la imagen. Ups. Entonces, si tienes una imagen, inserta la etiqueta de imagen y muéstrala, y luego muéstrame el nombre de usuario. Y ahora, hay una imagen y el nombre de usuario, y probablemente queramos estilizar esto un poco.
Entonces, creemos un archivo de estilo CSS para el diseño. De acuerdo. Y vamos a tener que cargar el diseño. De acuerdo. Y ahora vamos a CSS. Ahora, como es local, puedo decir directamente header. Puedo decir, bueno, puedo decir header. Oh, esto es un estilo aquí. Y luego quiero decir que desde el encabezado, quiero el borde de la imagen con un radio de esquina de 50%. Así que eso debería convertirlo en un círculo, y probablemente quiero tomar el encabezado y alinearlo de otra manera. Entonces, encabezado, display flex. Alinear elementos. Incorrecto. No. De acuerdo, ¿qué estoy haciendo mal? Colocar banderas. Oh sí, esa no es la forma correcta de hacerlo. No soy un experto en CSS como puedes ver. Justificar contenido flex y. Justificar contenido flex y. Justificar contenido flex. Ahí vamos. Ahora estoy aquí, por aquí. Pero probablemente también queremos un botón de cierre de sesión. Así que pongamos un botón de cierre de sesión también. Después del usuario, creemos un cierre de sesión. Y en lugar de iniciar sesión, tendremos una acción de cierre de sesión. Y así podemos hacer cierre de sesión. Cierre de sesión. Esto debe ser importado desde la ruta del complemento. Y ahí lo tienes. Ahora puedo hacer clic en cerrar sesión. Y ya no estoy conectado, ¿verdad? Perdí la imagen. Ahora dice iniciar sesión. Puedo iniciar sesión. Debería redirigirme a GitHub. Debería ir a autenticar y voilà, estamos de vuelta aquí, bastante sencillo.
Veamos. ¿Tenemos alguna pregunta? ¿Qué es el componente slot? Sí, excelente pregunta. Entonces, en el diseño aquí, tenemos un slot. Y la pregunta es, ¿qué es el slot? Bueno, vamos a comentarlo. Y observa que si lo comento, pierdo el contenido. Entonces, lo que hace el diseño es envolver el componente específico de esto. Es el índice que muestra la lista de usuarios. Y así necesitas saber dónde proyectar los hijos del diseño. Y eso se hace a través del slot. Entonces dices, espera un minuto. Eso es lo mismo que en React. Tenemos children. ¿No puedes simplemente usar children? Y esa es una buena observación. Y ciertamente podríamos hacerlo a través de children, pero los children tienen una propiedad particular que los hace no compatibles realmente con el modelo mental de Quix. Recuerda que el modelo mental de Quix es, mira, tengo un componente de diseño aquí, ¿verdad? He escrito código aquí dentro y tengo un comportamiento para iniciar sesión y cerrar sesión. Y luego dentro de este componente, tengo la cosa que muestra una lista de repositorios. Y Quix tiene, esta propiedad de que si interactúo con, con un componente hijo, ¿verdad? El, que muestra una lista de repositorios, entonces descargo ese componente específico. Lo que no descargo es el componente de diseño, ¿verdad? Porque el diseño no tiene interactividad por lo que no es necesario descargarlo. El problema es que si el diseño tuviera hijos aquí, entonces tendríamos que volver a ejecutar el diseño cada vez que los hijos cambien, ¿verdad? Entonces, cada vez que esto, iría e interactuaría con este componente que tiene una lista de repositorios, crearía un nuevo conjunto de hijos. Y ahora el diseño tendría que volver a ejecutarse para obtener un conjunto de hijos. Porque si lo piensas, los hijos son solo props. Y el problema es que este problema es recursivo. ¿Qué pasa si el componente, qué pasa si el componente de diseño estuviera en otro componente padre que también usaría children? Y así ahora tendrías que volver a ejecutar todos los componentes dentro de la cadena. Y así, una de las cosas que QUIC intenta realmente, realmente, realmente evitar es volver a ejecutar componentes, no porque sea necesariamente un problema de performance en un sentido de runtime performance, sino porque no queremos descargar nunca el código porque eso hace que el inicio de performance sea malo, ¿verdad? Entonces, para tener el mejor inicio de performance posible, quieres descargar la cantidad mínima absoluta de JavaScript. Y así, eso significa que quieres básicamente poder renderizar o volver a renderizar los componentes de manera independiente entre sí. Y para poder volver a renderizar los componentes de manera independiente entre sí, la proyección de los hijos debe ser declarativa. Entonces, si el diseño cambia, podemos volver a renderizar el diseño sin volver a renderizar el componente hijo. Entonces, si el componente hijo cambia, podemos volver a renderizar el componente hijo sin volver a renderizar el diseño. Y los hijos son de alguna manera porque el componente puede hacer operaciones en los hijos. Puede buscarlos, puede reestructurarlos, puede proyectarlos de diferentes formas, etc. Y así, realmente no tienes idea de lo que sucede con los hijos sin volver a ejecutar el componente. Y así, esto es lo que queremos evitar. Y así en Quake, los hijos son declarativos, y por eso los llamamos slots. Espero que eso no sea una respuesta demasiado larga. Lo siento, un momento.
Entonces, veamos. Así que fuimos, de acuerdo. Configuramos la autenticación, cambiamos el diseño para obtener la autenticación, y tuvimos un CSS para el diseño, y así creo que cubrimos todo, ¿verdad? Así que repasemos rápidamente. Entonces está esta RouteAction. En realidad no lo escribimos. El complemento lo proporcionó por nosotros. Entonces estas acciones son similares a los Routeloaders. Los loaders te dan data. La acción es lo opuesto, ¿verdad? El cargador envía data del servidor al cliente, para que el cliente pueda renderizarlo. La acción es lo opuesto. Realizas una acción en el cliente, como iniciar sesión y cerrar sesión, y quieres que se ejecute código en un servidor. Entonces básicamente estás enviando los datos en direcciones opuestas. Y las acciones están modeladas en el paradigma de publicación HTTP.
11. Botones Funcionales y Navegación
Short description:
En esta lección, aprendemos cómo hacer que los botones sean funcionales incluso sin JavaScript, navegar a diferentes páginas y obtener detalles del contenido de un repositorio específico. También exploramos la opción de navegación del lado del cliente en lugar de la navegación del lado del servidor. Al cambiar la etiqueta A por un enlace, podemos lograr la navegación del lado del cliente, reduciendo la necesidad de viajes de ida y vuelta al servidor. Esto mejora el rendimiento y permite una experiencia de usuario más fluida.
Entonces, si vas a la estructura, puedes ver que hay un formulario aquí, ¿verdad? Si busco el botón de cierre de sesión, verás que el botón de cierre de sesión es en realidad un formulario que apunta a una acción específica. La ventaja de esto es que incluso si desactivo JavaScript aquí, este botón seguirá funcionando incluso sin él. Y si deshabilito JavaScript, si actualizo la página, puedes ver exactamente lo que vería el SEO, ¿verdad? Esto es lo que vería el motor de búsqueda si hubieras navegado a tu página porque bueno, el SEO no tiene JavaScript deshabilitado. Así que volvamos a habilitarlo, y creo que hemos cubierto todo en esto, estoy pasando data entre rondas, pero no está aquí. ¿Preguntas en este punto? Hemos estado yendo durante un poco más de una hora. Entonces, tal vez hagamos otra lección, ¿la gente quiere un descanso después o están bien? Sigamos adelante. Es extraño tener una audiencia silenciosa. De acuerdo, asumo que el pulgar hacia arriba significa seguir adelante. Así que sigamos adelante. Pequeño descanso después de la lección tres. De acuerdo, suena bien. Así que hagamos un pequeño descanso después de la lección tres. Así que veamos, veamos la lección tres. Entonces, en esta lección, lo que queremos hacer ahora es mostrar los detalles de la página. Nuevamente, puedes ir tú mismo aquí, puedes ver el div, puedes ver la posición de inicio y finalización para esta lección en particular. Así que puedes ver todo lo que está sucediendo aquí. Y recomiendo que vayas y juegues con esto. Puedes revisar todo este repositorio y jugar con él por tu cuenta. Tendrás que crear las claves, las claves privadas, etc., pero las instrucciones están en el archivo ENP. Sí, este archivo aquí contiene las instrucciones sobre qué claves debes usar para obtener. De acuerdo, así que volvamos aquí. De acuerdo, así que hagamos una nueva ruta. Lo que nos gustaría hacer es que cuando estemos en esta página aquí, esto debería ser clickable para que pueda verlo. Y en realidad, antes de hacer eso, mejoremoslo un poco y en este intento. Veamos qué está pasando aquí. De acuerdo, deberíamos tener más texto aquí. Aquí está el texto. Tal vez hagamos esto un H3. Ahí vamos, de acuerdo. De acuerdo, nos gustaría hacer que estos sean clicables para que cuando hagas clic en ellos. Así que hagamos eso. Hagamos un ahref. Y la URL a la que iremos es slash, oops. GitHub slash, ¿verdad? Así que ahora, cuando puedes ver que es clickable y si paso el cursor sobre él, puedes ver la URL aquí abajo. Entonces, la URL es la URL a la que vamos. Entonces, si hago clic en esto, navegaré a una nueva página, que es GitHub MHAveryquick. Entonces, en este caso particular, la nueva ruta que acabamos de crear contiene el usuario y el nombre del repositorio, como puedes ver aquí. Y así, nuevamente, le voy a dar un componente. Debe ser una exportación predeterminada. Actualizo ahora. Debería decir, ¿por qué no dice nada? Source routes. No. Oh, lo arruiné, lo siento. Esto va aquí, no. Repos, oh, no está prestando atención. Lo siento por la confusión. De acuerdo, en GitHub, hay un usuario con un parámetro. Dentro de él, hay un repositorio, y dentro de él está el archivo de índice, que actualmente solo dice HelloQuick. Entonces, si navego, aquí está mi HelloQuick. De acuerdo. Entonces, lo que nos gustaría hacer es obtener detalles del contenido para este repositorio en particular. Y nuevamente, vamos a hacer trampa un poco, y voy a tomar un cargador de ruta aquí. De acuerdo. Esta es la importación del tipo, para que sepamos qué estamos devolviendo. Estoy seguro de que uno de mis JavaScript se niega a importar el archivo. Entonces aquí está nuestra respuesta de tipo, y lo que vamos a hacer es que vamos a tomar de los parámetros el usuario y el repositorio, ¿verdad? Esas son las dos partes. Y vamos a buscar los data de la URL de repositorios de GitHub. Y nuevamente, el token privado debe incluirse allí. Y luego la respuesta que obtendremos es Json, y ahora podemos hacer una conversión de tipo aquí. Y ahora nuestro repositorio es lo que vamos a devolver aquí, y si nuestro array superior, puedes ver que el cargador tiene el tipo correcto asociado con él. Entonces podemos decir const. Su repositorio, y aquí podemos hacer. Hagamos h1. Buen trabajo, de acuerdo. Y luego hacemos descripción. Y así imprime la descripción para nosotros aquí. De acuerdo, lo otro que probablemente nos gustaría hacer es hacer de esto un enlace de retroceso. Así que hagamos algo un poco complicado. Entonces, aquí haces a href. No, creo que eso es correcto. De acuerdo, ahora puede enlazar de vuelta al anterior. Entonces ahora básicamente podemos avanzar y retroceder. Ahora, lo que hay que entender sobre estos enlaces es que esta es una aplicación de varias páginas, ¿verdad? Así que estamos haciendo una actualización de página completa. Entonces, si hago clic aquí, es una actualización de página completa en el servidor para llegar aquí. Y si entro en uno específico como Quick, eso es una actualización de página completa para obtener el cliente. Ahora, Quick es bastante bueno en el rendimiento del lado del servidor. Y debido a que el inicio de performance es tan barato porque no hay hidratación, esto podría no ser un problema. Digamos que te gustaría hacer una navegación del lado del cliente en lugar de una navegación del lado del servidor. Entonces, todo lo que tenemos que hacer es, vayamos al último primero, todo lo que tenemos que hacer es cambiar la A por un enlace así. Impórtalo. Y ahora, cuando hagamos clic aquí, no hemos cambiado esto. Así que todavía es una actualización de página completa. Pero ahora, si avanzamos, ahora esto se convierte en una navegación del lado del cliente. Así que en realidad no hicimos un viaje de ida y vuelta al servidor. Básicamente hicimos una navegación del lado del cliente. Ahora, por supuesto, cuando haces una navegación del lado del cliente, significa que la información del enrutador también debe enviarse al cliente. Eso significa que toda la representación de estos componentes también ocurre en el cliente. Y así también podemos hacer lo contrario. Y podemos volver aquí y establecer esto como un enlace.
12. Navegación del lado del cliente y Cargador de rutas
Short description:
Al navegar entre páginas, Quick realiza la navegación del lado del cliente, reduciendo los viajes de ida y vuelta al servidor. El cargador de rutas se vuelve a ejecutar automáticamente al navegar a una página anterior, obteniendo los datos necesarios. Actualmente, Quick solo admite parámetros de ruta basados en cadenas, pero las actualizaciones futuras incluirán la tipificación para los parámetros de ruta y las URL. El cargador de rutas es una herramienta versátil que funciona tanto para la navegación del lado del cliente como del lado del servidor. En la próxima lección, exploraremos la integración de una página específica con Superbase para habilitar la funcionalidad de favoritos. En Quick, es posible realizar la precarga de rutas al pasar el cursor sobre un enlace utilizando un service worker para obtener los datos necesarios. Esta optimización garantiza que el código esté disponible cuando el usuario hace clic en un enlace. Al recopilar información estadística sobre los símbolos requeridos, el empaquetador puede optimizar los paquetes para navegaciones específicas.
Y ahora, tenemos el comportamiento de que estamos en el cliente. Estamos navegando a... Esto fue una navegación del lado del cliente. Podemos volver aquí, y es una navegación del lado del cliente. Así que la navegación ahora no está haciendo un viaje de ida y vuelta, sino que todo se hace en el cliente. La ligera demora que ves en realidad proviene del servidor que se comunica con GitHub, ¿verdad? Porque cuando navegas desde la página secundaria a la página anterior, el servidor tiene que hacer una búsqueda en GitHub de los datos y devolverlos al cliente. Ahora, lo interesante aquí es que pudimos cambiar entre una aplicación de múltiples promesas y una aplicación beta única simplemente cambiando un href por un enlace, y de repente se convirtió en una navegación del lado del cliente. Así que es bastante genial. Pero observa que mantuvimos nuestro modelo mental. Cuando navegamos a la página anterior, por lo tanto, si volvemos al propietario, vamos de esta página a esta página, observa que tuvimos que volver a ejecutar el cargador de rutas. Y así, el cargador de rutas se vuelve a ejecutar automáticamente sin que tengamos que hacer nada. Y la gran ventaja de este modelo es que, bueno, simplemente puedes, ya sabes, el componente simplemente dice que necesita esto. Y debido a que esta es una navegación del lado del cliente, automáticamente provocamos la obtención de los datos correctos para que todo pueda suceder. Y creo que eso es bastante genial.
¿Podemos escribir los parámetros? Sí, podemos escribir los parámetros, no solo reducir la solicitud. Sí, realmente podemos hacer eso. ¿A qué parámetros te refieres? Oh, oh, oh, ya veo. Estás hablando de estos parámetros aquí. Entonces, en el caso de los parámetros, siempre serán cadenas, ¿verdad? Porque el texto aquí siempre será una cadena, porque las URL son todas basadas en cadenas. Pero sería bueno si supieras que el usuario y el repositorio están permitidos, como usar un nombre de inicio de sesión o algo así, no está permitido. Así que sería bueno si esta información estuviera aquí. Aún no está disponible en Quick. Tenemos un prototipo en el que hemos investigado profundamente sobre esta idea de tener esto tipificado. Pero el prototipo aún no se ha convertido en un cambio completo. Entonces, esta es una función que vendrá en el futuro, no solo poder escribir los parámetros de ruta, sino también poder escribir estas URL y básicamente obtener un error si intentas navegar a una página que en realidad no existe. Ambas características estarán disponibles en el futuro, aún no están disponibles.
Excelente pregunta. No entendí la diferencia entre un cargador de rutas con múltiples páginas y una SPA. Entonces, si tienes una SPA, una aplicación de una sola página, realmente lo que tienes es un enrutador en el cliente porque cuando haces clic en un enlace, no quieres hacer una recarga completa de la página. En cambio, solo quieres calcular la diferencia para llegar al cliente. Y ahora que estás navegando desde esta página a esta página, esta página necesita datos. Específicamente, necesita repositorios. Así que volvamos aquí. Digamos que estamos dentro de esta página. Permíteme hacer una actualización completa de la página. Está claro que cuando hice una actualización completa de la página, el navegador no tiene idea de una lista de mis repositorios. Pero ahora, cuando hago clic en mi nombre y navego a esta página, tuvo que ir a buscar el conjunto de datos. Si observas la pestaña de Red y si miramos Fetch XHR, vemos que el navegador tuvo que hacer una búsqueda para esta cosa en particular. Y esta búsqueda, creo que es ¿Puedo obtener una URL? Obtendré una URL. Aquí vamos. Hizo una búsqueda en esa ruta en particular con una cola de destino especial de datos. Y así devolvió los datos asociados con este componente en particular. Y debido a que devolvió esos datos, luego pudo renderizar la interfaz de usuario. Entonces, mi punto es que estábamos usando, esencialmente, la idea del cargador de rutas, si estás familiarizado con Next.js, es algo así como obtener propiedades estáticas. Pero si haces una navegación del lado del cliente, que no creo que sea posible en Next.js, ¿cómo obtienes las propiedades estáticas? Tiene que haber alguna forma de obtenerlas. Y así, mi punto es que puedes tener un modelo mental único de cómo obtienes datos, que es el cargador de rutas. Y este modelo mental funciona tanto en la navegación del lado del cliente como en la navegación del lado del servidor. Espero que eso lo aclare más. OK, genial. Disculpen si los convencí. Pero sí, por favor, hagan preguntas. Me encanta. Hace que sea mucho más interesante para mí. OK, entonces veamos. ¿Qué más hay en la lección tres? Así que creamos una ruta. OK, entonces la próxima lección, vamos a tomar un pequeño descanso. Pero la próxima lección será lo que vamos a hacer es conectar esto, conectar una página específica con Superbase. Para que en Superbase podamos marcar esta página en particular como favorita. Así que quiero mostrarte cómo acceder a una integración para Superbase. Podemos usar esa información con datos. OK, eso no es lo que quiero. Lo siento, OK. ¿Se puede precargar una ruta al pasar el cursor sobre un enlace? Sí, en realidad, eso es exactamente lo que sucede. Así que si vamos a una ruta. Entonces, si vas a esta ruta aquí, esto es, ¿verdad? Básicamente ves que esto todavía parece un href regular. Pero observa que hay un prevent default. Si JavaScript está habilitado, esta navegación se evita. Así que estás evitando la URL. Y luego hay uno de estos scripts. No recuerdo cuál. Creo que es este. Hay un script que captura el evento de clic para esta cosa en particular para que pueda hacer una navegación del lado del cliente. Y eso puede enviar un mensaje al service worker para que vaya y precargue todos los datos para que la navegación sea instantánea. Permíteme mostrarte esto tal vez en la producción. Entonces, de esta manera, se hace aquí es que uno de estos scripts. Aquí vamos. Todo lo que tienes que hacer es enviar un evento de envío al service worker. QPREFETCH es escuchado por un service worker. Y básicamente, solo le dices al service worker cuáles son todos estos símbolos o fragmentos que necesitas. Y luego el service worker los precargará. Y así, de la misma manera, el LINQ-HREF puede notificar al service worker que, eh, esto es una posible cosa en la que el usuario podría hacer clic. Y porque el usuario podría hacer clic en esto, el service worker debería ir y precargar esa información. Y así es como se optimiza esto, es que cuando realmente tienes una aplicación en ejecución, entonces en la aplicación en ejecución, puedes recopilar información estadística sobre qué símbolos se necesitan, cuándo. Y luego le dices al empaquetador que optimice tus paquetes para esas navegaciones. Lo siento, ese es un tema un poco más avanzado. Pero sí, la respuesta corta es que sí, absolutamente puedes hacer eso. Entonces también puedes precargar eso. Entonces, si el precargador está funcionando correctamente, nunca deberías encontrarte en la situación de que el usuario hace clic en algo y el precargador no tiene el código para ti.
13. Creación de puntos finales y middleware con Qwik
Short description:
Qwik puede crear puntos finales fácilmente declarando un método on-get en una URL específica. También se pueden crear funciones de middleware en el archivo de diseño para envolver otros componentes y prevenir valores predeterminados. Superbase se puede instalar y utilizar para configurar un proyecto con una base de datos. No es posible tener más de una función onGET en un archivo, pero onGET y onRequest pueden coexistir. La diferencia entre un cargador de rutas y una función on-get es que esta última es un primitivo de nivel inferior que proporciona acceso completo a la solicitud y respuesta HTTP, mientras que el primero es un concepto de nivel superior que devuelve datos y permite respuestas JSON.
Entonces, cada interacción debe ser recibida con una coincidencia en la caché del cliente. Lo que hicimos fue la navegación del lado del cliente. Te mostré cómo podemos hacer tanto la navegación del lado del servidor como del lado del cliente. En realidad, quiero mostrarte otras cosas. Qwik también puede hacer middleware y puntos finales. Digamos que queremos crear un punto final para algunos de nuestros datos. Creemos un nuevo archivo. Hagamos un API/pollet solo para datos. No es 6. OK, puedes hacer on-get, exportar const get, controlador de solicitud. Sí, OK, lo que quiero mostrarte es que no voy a profundizar demasiado. Solo quiero mostrarte que puedes crear fácilmente puntos finales haciendo 200. Así que solo declarando un método on-get en una URL específica, puedes crear fácilmente un punto final. Esto está dentro de API/datos. Así que si voy a localhost:3000/API/datos, puedes ver que devuelve un conjunto de datos. Así que fue súper, súper fácil crear un punto final en nuestra aplicación. Ahora, al igual que puedes crear un punto final, también puedes tener middleware. Así que vamos al archivo de diseño de nivel superior. Y aquí, podemos crear un on-request. Exportar. Si bien on-get solo responde a solicitudes GET, on-request responde a todo con un controlador. Y es igual a. Gracias. ¿De qué te quejabas? Oh, espera, ¿qué? ¿Por qué está aquí el on-request? No, se supone que no debería estar aquí. Está bien, se supone que debe estar aquí. Ahí lo tienes. Así que ahora lo que podemos hacer es decir console.log. Y podemos hacer request.url.restrict. Ahora tenemos un middleware, y puedes ver que cualquier URL a la que navegue, como por ejemplo esta, puedes ver que imprime la navegación aquí. Si actualizo esta página, puedes ver que esta URL ha sido. Así que es muy fácil y rápido no solo crear puntos finales, sino también crear funciones de middleware. Básicamente, los puntos finales van en index.tsx, y el middleware esencialmente va en el diseño para que puedas envolver otras cosas y prevenir valores predeterminados. Por ejemplo, si quisieras hacer autenticación, podrías mirar fácilmente la cookie y decir que si no tienes la cookie correcta, redirige a otro lugar en lugar de ejecutar el diseño normal. Es un poco de desvío. Pero veamos, ¿dónde estamos? Oh, sí. Así que queríamos configurar un Superbase. Instalemos Superbase. Vamos a deshacernos de este middleware para no tener todos esos registros en la consola. Instala Superbase. Y sigue adelante y crea el proyecto. Creo que ya he creado un proyecto. Permíteme mostrarte. Tengo un proyecto llamado Masterclass. Y dentro de este proyecto, ¿puedes tener más de un onGET en un archivo? No puedes tener más de un onGET porque en ESM solo puedes exportar una función de un nombre dado. Así que no puedes tener más de un onGET. Pero ciertamente puedes tener un onGET y un onRequest. Así que puedes tener dos onGET, uno onGET y uno onRequest. Puedes tener dos funciones de nombre diferentes. Y ciertamente puedes tener onGET en todos los archivos de diseño en el medio. No estoy seguro si hay un caso de uso para tener más de un onGET, como decir que ambos deben ejecutarse. Y dado que es el mismo archivo, simplemente ponlos en la misma función. Espero que eso responda la pregunta. Pero ciertamente puedes tener onRequest y onGET en el mismo archivo. Y ciertamente puedes componerlos colocándolos dentro de los archivos de diseño en la solicitud que veré. OK, ya he pasado por esto y he creado una base de datos llamada Favoritos. Y si voy y miro dentro de ella, las tablas, ¿cómo entro en la base de datos? Solo muestra la base de datos. Quiero ver los datos. OK, ¿por qué olvidé cómo hacer esto? Hay una tabla, ¿verdad? Hay siete filas. ¿Cómo veo las siete filas? Tú, tú, tú, tú, tú, tú. He olvidado cómo usar esta herramienta. Base de datos. Ese es el editor de tablas. Base de datos. Aquí está mi tabla. ¿Por qué no puedo hacer clic en la tabla? División. He olvidado cómo usar esta herramienta. BGMI. Base de datos. Oh, aquí vamos. Muy bien. Así que aquí están nuestros registros existentes. Y así intentaremos básicamente tener un botón de favoritos que te diga si un proyecto en particular está marcado como favorito según tu nombre de usuario y repositorio y usuario. Pero antes de entrar en eso, déjame hacer una pregunta. ¿Cuál es la diferencia entre un cargador de rutas y una función on-get? OK, esa también es una muy buena pregunta.
14. Uso de Route Loader e Integración de SuperBase
Short description:
La función on-get proporciona acceso de bajo nivel a la solicitud y respuesta HTTP, lo que permite un control total. En cambio, el cargador de rutas es un concepto de nivel superior que abstrae el acceso de bajo nivel y permite una recuperación más fácil de datos. Se pueden componer varios cargadores de rutas en una sola solicitud para una ruta. El cargador de rutas es una forma de alto nivel de obtener datos, mientras que el punto final proporciona más control pero requiere más responsabilidad. Conectémonos a SuperBase y obtengamos datos. Creamos un cliente de SuperBase y consultamos la conexión. El mapa compartido permite que los cargadores de rutas se pasen datos entre sí. La sesión, obtenida del mapa compartido, contiene información sobre el usuario actualmente conectado.
Entonces, la diferencia está en cómo se utiliza. Por lo tanto, on-get está destinado a ser algo de nivel inferior. Puedes pensar en on-get como un primitivo de bajo nivel que te brinda acceso completo a la solicitud y respuesta HTTP. Desde aquí, puedes establecer la respuesta, establecer las cookies, básicamente hacer cualquier cosa que desees con una solicitud y respuesta HTTP. El cargador de rutas se basa en on-get y es un concepto de nivel superior. En lugar de obtener un punto final, que es una forma específica de JSON que controlas, el cargador de rutas no te brinda acceso de bajo nivel, simplemente dice, ¿cuál es el dato? Aquí, puedes devolver lo que quieras. Normalmente, devolvemos datos JSON porque estamos hablando con otro servicio JSON. Pero aquí, podrías devolver otras cosas. Puedes devolver objetos que tienen ciclos. Puedes devolver funciones, closures y muchas otras cosas. Debido a eso, el formato JSON no está destinado a ser algo que consumas. En cambio, es un detalle de implementación que sucede por debajo. Además, la forma en que consumes el cargador de rutas es simplemente obteniéndolo. Desde la perspectiva del desarrollador, simplemente estás llamando a una función getter que te brinda esta cosa. El hecho de que en el entorno del servidor, se comunique directamente con la función es algo que sucede por debajo. Pero luego, en el entorno del cliente donde realizamos una navegación del lado del cliente, hacemos algún tipo de solicitud HTTP personalizada para obtener los datos que están ocultos para ti. Otra cosa que debes entender es que cuando hago una navegación del lado del cliente, no solo estoy ejecutando este cargador de rutas, sino que también estoy ejecutando este cargador de rutas aquí porque forma parte de la ruta de solicitud. Por lo tanto, puedo obtener cargadores de rutas de forma aditiva. Es decir, puedes tener muchos de ellos dentro de los diseños. ¿Tengo uno aquí? Lo siento. No creo que tengamos uno aquí. Podemos poner varios de ellos en muchos lugares diferentes y todos se componen en una sola solicitud para la ruta. En este caso particular, este es solo uno de los muchos cargadores de rutas diferentes que se activaron para traer los datos. Por lo tanto, puedes pensar en los cargadores de rutas como una forma de alto nivel de obtener datos en la que no tienes que pensar en cómo establecer los parámetros de consulta o cómo serializar los datos. Todo esto se abstrae. Es un concepto de nivel muy alto y solo te preocupas por obtener el valor. El valor que obtienes aquí es una señal, lo que significa que si el cargador de rutas se vuelve a ejecutar y se actualiza, esta señal puede provocar una nueva representación del conjunto de datos, ¿verdad? El cargador de rutas es mucho más alto nivel que un primitivo como un punto final. El punto final solo te permite controlar todo, pero eres responsable de todo. Espero que tenga sentido. Bien, volvamos a conectar esto a SuperBase. Hemos instalado SuperBase y volvamos a ejecutar el servidor. Ahora que SuperBase está instalado, naveguemos a Quick aquí. Si vamos a nuestra base de datos, vemos que, ¿esto es favorito o no? No, lo es, y ya hemos leído Quick, ¿verdad? Porque esta fila en particular, esta fila en la base de datos ya existe. Hagamos esto más pequeño, no. Bien, nos gustaría obtener estos datos. Y la forma de obtener los datos es, así que hagamos esto. Así que obtengamos nuestro repositorio, así que estamos aquí. Estamos en... Lo siento, esta vista. Por lo tanto, nos gustaría obtener los datos de uso es favorito. Y por ahora, simplemente voy a devolver un número aleatorio y básicamente diré, a veces diré que es favorito y a veces diré que no es favorito solo para hacer un punto. Y observa, ahora tenemos dos cargadores de rutas separados, por lo que los cargadores de rutas van al punto anterior, ¿verdad? Y estos dos cargadores de rutas están obteniendo diferentes datos, pero se componen en una sola solicitud si es una navegación del lado del cliente. Y si es una navegación del lado del servidor, entonces ni siquiera hay una solicitud, el servidor simplemente hace todas las partes. Entonces aquí vamos a obtener que es favorito y justo aquí, nos gustaría imprimir un botón y nos gustaría mostrar si es favorito o no. Entonces, si es favorito, voy a insertar un emoji, una estrella. Aquí vamos. Oops. ¿Qué le pasó a mi emoji? Bien, ahora tenemos una estrella sólida y un contorno de la estrella. Entonces, ahora si voy aquí, ahora puedes ver que al azar, simplemente cambiará, ¿verdad? A veces se muestra y a veces no se muestra. Ahora tenemos un cargador de rutas que carga los datos y luego pasamos los datos a su favorito y en función de eso, representamos diferentes estados. En lugar de hacer esto, hablemos realmente con SuperBase. Hagamos la solicitud. Por lo tanto, crearemos un cliente de SuperBase. Nuevamente, deberás obtener la URL y las claves y esto es un evento de solicitud, así. Y ahora tenemos un SuperBase. Esto nos brinda una conexión y ahora nos gustaría consultar la conexión. Primero, antes de hacer eso, vamos a const. Olvidé la sintaxis. ¿Es user? Charmar repo? ¿Cómo se hace? Olvidé cómo hacer esto. Lo siento. Hay una sintaxis que podemos hacer. Hagamoslo en tomas separadas. Espera. ¿Lo hizo? Solo se queja de que no se usa. Oh, creo que lo obtuve correctamente. Oh, simplemente lo escribí mal. OK, así que obtuve la sintaxis correcta. Entonces tenemos un usuario. Y luego tenemos un repositorio. Oh, también necesitamos obtener los usuarios que han iniciado sesión actualmente. Obtengamos una sesión compartida. Todos estos cargadores de rutas pueden pasarse datos entre sí. Ese es el mapa compartido. Aquí, hagamos esto. Y lo que queremos hacer es decir const user = session.user.email.
15. Alternar Estado Favorito e Interacción con la Base de Datos
Short description:
Podemos obtener el correo electrónico del usuario de la sesión y usarlo para obtener datos de la base de datos de SuperBase. Al configurar una acción, podemos alternar el estado favorito de un repositorio. El objeto de formulario conoce la propiedad 'favorito' y su valor booleano. Podemos usar Zod para proporcionar tipos sólidos para el formulario. Al hacer clic en el botón, se ejecuta la acción, que interactúa con la base de datos. Se recomienda refactorizar el código e implementar las mejores prácticas. El cliente de la base de datos nos permite realizar operaciones útiles, como marcar o desmarcar como favorito un repositorio. El código para marcar como favorito es asíncrono.
Entonces, ¿qué podemos hacer? Podemos decir const user equals session.user.email. Creo que esto es realmente una sesión. Pero creo que podría ser nulo o indefinido si no está bloqueado. Y necesitamos ingresar esto. Y así esto quiere ser un signo de interrogación. No está en contra del signo de interrogación, pero es un signo de interrogación. OK, así que ahora en lugar de sesión, simplemente ponemos usuario. Así que ahora veremos. Oh, el correo electrónico no es usuario. OK, así que ahora puedes ver que tienes una solicitud, que la sesión me muestra mi correo electrónico actual y que actualmente estoy obteniendo el [? emyhevry,?] Así que emhyvry rápido. Y [? emyhevry?] está conectado, por lo que está mostrando mi nombre aquí. Así que puedes obtener todas las partes aquí.
Ahora que tenemos un cliente de SuperBase, nos gustaría determinar, en lugar de decidir al azar si está marcado como favorito o no, nos gustaría obtenerlo. Entonces, si super-base, tenemos la sintaxis. Me disculpo si ves. Entonces, la sintaxis es obtener el cliente de SuperBase, de la tabla favorita. Recuerda, creé la tabla de antemano. Selecciona todas las columnas, pero solo si el correo electrónico es el correo electrónico del usuario y el repositorio son los valores que he extraído. Mostrar un error en caso contrario, de lo contrario, dices favorito.vinculado. OK, así que ahora estamos diciendo, como, hey, si devolvemos algún dato, entonces probablemente sea favorito. Bueno, no lo es, probablemente sea favorito. Y si no devolvemos ningún dato, entonces no lo es. Así que ahora que navego aquí, puedes ver que se muestra como favorito. Ya no es aleatorio, ¿verdad? Siempre lo muestra. Y la razón por la que muestra eso es porque si vas a la base de datos de SuperBase, puedes ver que mishko, repo, rápido, y Hevery están marcados como favoritos, ¿verdad? Y así está aquí. Ahora lo que me gustaría hacer es si hago clic en esto, actualmente no hace nada, debería ir y cambiar el valor dentro de la base de datos. Hagamos eso a continuación. Entonces, lo que nos gustaría hacer es configurar una acción. Así que vamos a sumergirnos en las acciones. Exportemos const, use toggle favorite, perfecto, amo la IA. OK. Así que ahora hacemos esto y, en realidad, se llama datos. Todavía estoy en ese nodo alrededor de la acción. Datos, oh lo siento, no se trata de, un poco alrededor de la acción. Es formulario, eso es lo que dice, OK. Muy simple. Luego podemos colocar el formulario en una acción aquí. Necesitamos importar esto. OK, acabamos de crear un botón dentro del formulario. Entonces, si miras lo que se está representando aquí, ¿verdad?, puedes ver que hay un botón y este botón está dentro de un formulario y este formulario apunta a una acción en particular, ¿verdad? Y así, la sesión, ¿de dónde viene esto? Aquí está. OK, así que ahora si hago clic aquí, voy a enviar el formulario. Y lo que puedes ver es que dice use toggle favorite. ¿Verdad? El objeto de formulario aquí. Aquí, este objeto de formulario está vacío. No tiene nada interesante. Y así, una forma típica de hacer esto con formularios es decir tipo de entrada igual oculto, el nombre es favorito. Y el valor que queremos mostrar aquí es, bueno, si actualmente es favorito, si actualmente es favorito, entonces no queremos que sea favorito. De lo contrario, si no es favorito, entonces queremos que sea verdadero, ¿verdad? Así que ahora, ¿verdad?, porque es favorito, si hago clic en él, entonces imprime favorito es igual a nada, ¿verdad? Así que este objeto literal tiene básicamente este valor de entrada del formulario. Pero si te pones encima, ves que es solo el tipo genérico llamado objeto de valor JSON. No es lo suficientemente específico. Y así lo que nos gustaría hacer es usar Zod para darle tipos sólidos. Entonces Zod y lo que vamos a hacer aquí es decir que tenemos un favorito y será z.obj. OK. OK. Así que ahora, cuando hacemos clic en él, notamos que si me pongo encima de un formulario, ya no es un objeto de valor JSON genérico. Ahora el formulario sabe que hay una propiedad llamada favorito y es un booleano, ¿verdad? Vamos a probarlo. Así que si presiono este botón, nota que obtengo un error de validación de Zod porque lo que Zod me está diciendo es que, hey, esperaba un booleano, pero en cambio obtuve una cadena. Y así una cadena no es un booleano y así suceden cosas malas. Así que lo que tenemos que hacer es decir curso. Esto le dice a Zod que convierta la cadena en un booleano. Y así, nuevamente, si me pongo encima de aquí, puedes ver que, ¿por qué no me está mostrando? ¿Qué? Debería mostrarme que es un booleano, oh, bueno, OK. Sé lo que estaba pasando. Ahora muestra correctamente que es un booleano. OK, así que si actualizo y hago clic en este botón, nota que dice que, hey, fue marcado como favorito. Y había un falso aquí. Y así, si voy y, por ejemplo, olvido tener el campo de entrada, si comento esto y si hago clic en este botón, ahora, oh, porque hace un corgi. Ja ja. OK, así que la falta de contenido es lo mismo que falso. Y así en este caso particular, lo convirtió a booleano. Así que asume que es falso, OK. Si no hubiera un corgi, pero sería como una cadena, entonces la cadena te daría un error diciendo, hey, no encontré este valor en particular. OK. Así que al hacer clic en este botón, ejecuta este console.log. Y así nos gustaría hablar realmente con la base de datos y hacer algo útil aquí. Voy a copiar este fragmento de código que está hablando con la base de datos. Y en realidad vamos a necesitar toda esta información. OK, así que ahora copiamos todo este código. Obviamente puedes refactorizar esto a métodos comunes y mejores prácticas, etc. Pero solo quiero mantenerlo simple y tomar esto y obtenerlo como secundario. Así que ahora tenemos un cliente de base de datos simple con el que podemos hablar.
16. Acciones de Favorito y Desfavorito
Short description:
Ahora podemos ejecutar código para marcar como favorito o desmarcar algo. El código para marcar como favorito implica una operación de inserción o actualización (upsert), que inserta un nuevo valor si no existe o actualiza el valor existente. Por otro lado, para desmarcar como favorito, eliminamos los datos. Todo este proceso ocurre en el lado del cliente, incluso si JavaScript está deshabilitado. Las acciones funcionan enviando programáticamente un formulario y ejecutando la acción de alternar favorito. Después de que se ejecuta la acción, se actualizan los datos de la consulta, lo que provoca una nueva representación del formulario y la información asociada. Esto asegura que, incluso si JavaScript está deshabilitado, las acciones sigan funcionando correctamente.
Entonces ahora podemos decir, si, en lugar de un formulario, solo vamos a decir favorito aquí. Así que si es favorito, ¿verdad? Ahora podemos ejecutar código aquí. Si quieres marcarlo como favorito y si no quieres marcarlo como favorito. Así que marcar algo como favorito, el código para eso es, Voy a hacer trampa aquí y mirar mi solución. Bien. Y esto tiene que ser asíncrono. ¿Qué es lo asincrónico? En realidad es un poco más complicado. Así que, si estamos conectados, ¿verdad? Porque si no estamos conectados, entonces no podemos hacer esto. Así que si estamos conectados, entonces miramos el favorito y hacemos algunas cosas. Así que si estamos conectados y nos gusta, entonces lo que queremos hacer es insertar en la base de datos el correo electrónico, el usuario y un repositorio. Aquí, observa que no dice insertar. Dice upsert. Dos, bien. Entonces, upsert es una inserción que hará una actualización o una inserción. Eso es lo que se llama un upsert. Y así, básicamente dice, si ya existe, entonces solo actualiza el valor. Y si no existe, entonces inserta un nuevo valor. Así que eso es básicamente lo que hace el upsert. Así que vamos a hacer eso en caso de que lo tengamos. Y en caso de que no queramos que sea favorito, bueno, simplemente tenemos que eliminarlo, ¿verdad? El código para eliminar está aquí. Bien, así que si quieres que sea favorito, entonces hacemos un upsert. Si no quieres que sea favorito, entonces vamos y eliminamos lo que ya está en la base de datos. ¿Verdad?, y así nuevamente, Zot hace la tipificación de datos por nosotros. Y así, ahora tenemos una buena acción. Así que ahora, si vamos a nuestra aplicación, cuando hago clic en esto, puedes ver que dice, usó toggle false, ¿verdad?, así que no lo queremos. Pero observa que el botón, en realidad, eliminó los datos. Lo que sucedió fue que hicimos clic en este botón, este botón hace que el formulario se envíe. Ahora, aunque estamos enviando un formulario, en realidad todo esto se hace en el cliente, porque este formulario tiene prevent default. Así que en realidad no estamos enviando, estamos fingiendo, estamos fingiendo hacer un viaje de ida y vuelta al servidor, pero en realidad eso no es lo que está sucediendo. Simplemente estamos haciendo un post directamente. Así que si miras la pestaña de red, vamos a actualizar esto de nuevo, y si haces clic aquí, observa que hicimos programáticamente un post de Q data con favorite igual a true. En realidad no hicimos un viaje de ida y vuelta. Así que esto no es un viaje de ida y vuelta. Esto es un envío programático del formulario. Así que entramos en el formulario y luego se ejecuta la acción de alternar favorito. Ese es este código aquí. A partir de aquí, averiguamos si queremos que se marque como favorito o no. Extraemos el nombre de usuario y el repositorio del pasado, extraemos la dirección de correo electrónico del mapa compartido que se colocó allí con el complemento de autenticación. Así que ahora tenemos un correo electrónico y ahora decimos, hey, si estamos conectados lo que significa que tenemos un correo electrónico hacemos una inserción o una eliminación de los datos pero debido a que es una acción, las acciones se ejecutan antes de los cargadores de ruta. Y después de que esto se ejecuta, volvemos a ejecutar use is favorite. Y en este caso particular, volvemos a consultar los datos, simplemente los actualizamos. Y ahora los datos de la consulta dicen que ya no somos favoritos. Y así se actualiza esta señal, para decir, oh, ahora esta señal y ahora ya no eres favorito. Y debido a que la señal se actualiza, provoca una nueva representación del formulario pero principalmente de esta información aquí. Así que todo esto básicamente ocurre en el cliente. No es un viaje de ida y vuelta al servidor. Así que el modelo mental desde el punto de vista del desarrollador es como si estuvieras fingiendo hacer solo un post en la aplicación y luego obtener una representación completa pero en realidad, en el lado del cliente, lo que está sucediendo es que estás haciendo todo en JavaScript. Pero un efecto secundario interesante de eso es que en realidad puedes deshabilitar JavaScript. Así que incluso si el JavaScript está completamente deshabilitado, aún puedes marcar y desmarcar cosas porque en este caso, el JavaScript está deshabilitado y, por lo tanto, prevent default no tiene sentido. Y así hacemos un post normal. Así que si vas a todo, puedes ver que estamos haciendo un post normal y luego la respuesta en este caso particular no es solo una actualización de nuestros datos sino una respuesta completa en HTML que se renderiza en un servidor. Así que la buena propiedad de las acciones es que funcionan incluso si el JavaScript está deshabilitado.
17. Configuración de Super Base y Cargador de Rutas
Short description:
Hemos cubierto la configuración de Super Base, el uso del cargador de rutas y la acción de ruta para obtener y actualizar datos, y el uso del formulario para enviar datos. Actualmente, el cargador de rutas siempre se vuelve a ejecutar, pero hay una próxima API que permitirá reglas de caché para optimizar el rendimiento al determinar qué cargadores de rutas deben volver a ejecutarse. Esta función aún no está disponible.
De acuerdo, creo que es un buen momento para hacer una pausa y ver si hay preguntas. Así que adelante e interrúmpeme si tienes algo en mente. Echemos un vistazo. Entonces configuramos una Super Base. Usamos el cargador de rutas para obtener data de la Super Base. Usamos la acción de ruta para actualizar data de la Super Base y luego usamos el formulario para enviar data. Creo que hemos cubierto todo aquí. De acuerdo. Así que creo que hemos cubierto, ¿podemos evitar que el cargador de rutas se vuelva a ejecutar si la acción no influye en el resultado para optimizar el rendimiento? Buena pregunta. En este momento, la respuesta es no, el cargador de rutas se vuelve a ejecutar todo el tiempo, pero estamos trabajando en una API, que creo que está en proceso. Así que espero que esté disponible en las próximas semanas o una o dos semanas. Y esta API te permite establecer reglas de caché en la acción de encabezados de caché, puedes pensar en ello como encabezados de caché, no realmente un encabezado de caché. Y básicamente esto utilizará estrategias de caché para indicarle al sistema qué parte del sistema, qué cargadores de rutas han sido invalidados por tus acciones y cuáles no. Y como resultado, puedes obtener actualizaciones adecuadas o puedes ahorrarte la molestia de comunicarte con la base de datos, si sabes que un enrutador en particular no necesita volver a ejecutarse. Así que esa función está por venir, aún no está disponible.
18. Conceptos Avanzados y Seguimiento de Usuarios
Short description:
Hablemos de conceptos avanzados y creemos una nueva ruta para mostrar una lista de repositorios favoritos. Podemos usar el código proporcionado y modificarlo para devolver los repositorios favoritos. También podemos implementar un cuadro de búsqueda con una función de debounce para buscar nombres de usuario específicos. La función useTask es similar a useEffect en React pero con algunas diferencias. Nos permite realizar un seguimiento de los cambios en el valor del usuario y retrasar la ejecución de una función. La función useTask es útil para crear efectos secundarios que ocurren fuera de la aplicación. Puede ser asíncrona y requiere un seguimiento explícito. Por otro lado, useComputed se utiliza para valores derivados que se pueden obtener de forma síncrona a partir del estado existente. UseComputed no requiere un seguimiento explícito y se actualiza automáticamente. Otra opción es useResource, que nos permite obtener valores de un estado externo.
Lo que quiero decir con conceptos avanzados es que podemos hacer cosas realmente complicadas. Así que creemos una nueva ruta, que mostrará un conjunto de usuarios. Dentro de aquí, vamos a crear un nuevo archivo, index.tsx. Y como siempre, debemos tener un componente predeterminado. Así que aquí, voy a borrar todo. Solo veremos, hola quick, ¿de acuerdo? Y lo que me gustaría hacer es mostrar una lista de, vamos a mostrar una lista de todos tus repositorios favoritos, ¿de acuerdo? Así que voy a hacer un poco de trampa y copiar el código aquí. Oh, veo que este es un código diferente, de acuerdo. Así que usaremos este favorito, de acuerdo. Permíteme copiar este código aquí. Aquí. Y aquí. De acuerdo, y en lugar de devolver la longitud, voy a devolver un favorito, y eso será, no tengo información de tipo configurada para Super Base, pero definitivamente podrías hacerlo, hay cosas que podrías hacer. Así que vamos a decir que vamos a tener un correo electrónico de cadena de usuario, oh, perfecto, de acuerdo. No sé cómo compilar una nueva lista, pero hay información correcta. De acuerdo, ahora vamos a obtenerla. Entonces eso no es es favorito, use favoritos. Vamos a conectar eso a todo, para que Experian se convierta en un segundo método. Ahí vamos. Guardando esto. Creo que ya tenemos la demostración en marcha, así que guárdalo exactamente como hicimos la demostración, y luego podemos olvidarnos de ello. Y luego todo lo que hemos hecho hasta ahora, y podemos ir a alimentar nuestro reloj, que será la primera ronda de creación de medios. Y luego el laboratorio, que será el último que usemos para la creación de medios. Voy a mostrarte dos formas diferentes de hacerlo en un minuto. Voy a crear un usuario, que alimenta este índice, vamos a ver, sí, solo, De acuerdo, vamos a ver, todo porque creamos gris, queremos consultar el uso de un repositorio específico, y voy a poner todo esto, ahí vamos, así que aquí está nuestra lista de favoritos. Así que hay dos, de acuerdo, así que tenemos una lista de favoritos aquí y puedo hacer clic en cualquiera de ellos y abrirlo en un archivo separado y venir aquí. Así que eso debería ser bastante sencillo, así que hagamos lo siguiente, que es, me gustaría ejecutar, básicamente, me gustaría tener un cuadro de búsqueda aquí, que me permita buscar cualquier nombre de usuario específico en él, así que veamos, creo que lo que tengo en mente está aquí, es input.text usuario. El usuario necesita usar señal. Entonces, ya sabes, solo tengo nombre de usuario y tengo que escribir aquí, y me gustaría mostrar todos los usuarios que están en ese documento, allí. Pero como quiero comunicarme con el servidor, no quiero abrumar al servidor, y lo que realmente quiero es tener un debounce del servidor debounce, debounce usuario, que es, bueno, ¿qué es esto? Que es un, es lo mismo que un usuario, pero retrasado, ¿verdad? Entonces, al imprimir debounce usuario punto valor, me gustaría verlo retrasado. Para eso hay algo llamado useTask. Entonces, useTask es similar a useEffect para las personas que están familiarizadas con React, pero hay suficientes diferencias que pensamos que nombrarlo exactamente igual causaría confusión. Y aunque puedes pensar en ello como useEffect, hay suficientes diferencias entre cómo funciona useEffect y cómo funciona en Quick que vale la pena profundizar en ello. Así que lo que voy a hacer es decir rastrear y vamos a decir eso. Así que básicamente estamos diciendo, oye, cada vez que cambie el valor del usuario, queremos volver a ejecutar esta función. Hasta ahora, no hace nada útil. Así que lo que voy a hacer es decir, setTimeout. Y vamos a decir que debounce usuario punto valor es igual al valor después de 500 milisegundos. Y luego también tenemos que hacer una limpieza. Así que si, si esta función se vuelve a ejecutar antes de que, ya sabes, antes de que pasen 5 milisegundos, entonces deberíamos hacer una limpieza o borrar el temporizador, ¿verdad? Y ahora, fíjate que hay un nombre de usuario aquí y puedo escribir Hevery, y mientras escribo, no sucede nada, pero en el momento en que dejo de escribir medio segundo después, M Hevery aparece en esta página. Lo siento, solo estaba volviendo a leer la pregunta, ya respondí esto. De acuerdo, como puedes ver, hay un retraso, ¿verdad? Hay un retraso de medio segundo, pero fíjate que mientras sigo escribiendo, el retraso de medio segundo no se aplica. Solo ocurre cuando dejo de escribir, ¿verdad? Así que básicamente estamos configurando una tarea y la tarea dice, oye, cada vez que el valor del usuario cambie, porque hay un seguimiento aquí, vuelve a configurar un temporizador y este temporizador, este temporizador establece el valor del usuario debounce, a la valor actual de lo que te da el seguimiento pero es un retraso de 500 segundos y, por supuesto, hay una función de limpieza que, si esta función se vuelve a ejecutar antes del otro lado, entonces no está bien. Ahora podrías preguntarte, como, sí, pero, como en React, solo pones las suscripciones aquí al final. Claro, pero surge el mismo problema, que es que la única razón por la que funciona en React es porque React vuelve a ejecutar el componente todo el tiempo, ¿verdad? Mientras que si hago un console log aquí, si hago un render, voy a ver un render en un servidor, pero no veo un render en el cliente. Incluso si escribo, el render aún no ocurre en el cliente. ¿Cuál es la diferencia entre useTask y createEffect sólido? ¿Por qué necesitas hacer un seguimiento? ¿No puede saber automáticamente que hay una señal y volver a ejecutar? De acuerdo, todas estas son buenas preguntas. Entonces, useTask es, en muchos aspectos, muy, muy similar a createEffect, pero hay un par de diferencias. La primera diferencia es que esta tarea puede ser asíncrona. Por lo tanto, podríamos reescribir esta función de la siguiente manera. Entonces, digamos que tenemos const delay igual a, delay igual a, sí, de acuerdo. Oh, cierto, pero esto no nos dará una limpieza. De acuerdo, eso está bien, podemos hacerlo de manera diferente. Podemos tratar esto y la limpieza es una función que toma un B, que es un número, creo cuando devolvemos. Y luego tenemos ID. ¿Esto va a funcionar? Yo, yo, yo, no te gusta, lo siento. Obtener término si me caigo, así. De acuerdo, lo que podemos hacer es reescribir este código como await delay 500 cleanup. Oh, lo siento, lo siento, me perdí aquí. La limpieza es una devolución de llamada, que es una función que toma, que produce. Estoy complicando esto innecesariamente, lo siento por eso. En este caso particular, esta función ahora es asíncrona. Y así solo necesitamos hacer esta parte. De acuerdo. Sí, funciona. De acuerdo, esta es una implementación alternativa. Y lo que hay que entender aquí es que ahora se nos permite hacer una declaración await. Entonces, la primera diferencia es que useTask es asíncrono. Puede ser sincrónico y, por lo tanto, está destinado a efectos secundarios. Y, por lo tanto, está destinado a no realizar un seguimiento automático. El problema es que si pones el valor del usuario aquí podrías realizar un seguimiento automático. Pero si lo pones detrás de la declaración await no podrías realizar un seguimiento automático. Y ahora tienes una elección. Puedes tener una API que diga, de acuerdo podemos hacer un seguimiento automático pero no puedes tener funciones asíncronas. O puedes tener una API que diga puedes tener un seguimiento asíncrono, pero solo puedes tener un seguimiento automático antes de la declaración await pero no después de la declaración await. O puedes tener una API que sea mucho más consistente y decir, oye, simplemente, cuando sea asíncrono simplemente no puedes hacer un seguimiento automático. Y así, porque queremos que esta cosa realmente tenga efectos secundarios fuera de la aplicación elegimos no hacer un seguimiento automático en este caso pero fíjate que en el otro ejemplo, que estaba aquí estábamos usando useComputed, ¿verdad? Y useComputed no necesita seguimiento. Y eso es porque useComputed debe ser síncrono. Y el modelo mental es que si estás haciendo un valor derivado que se puede obtener de forma síncrona a partir de un estado existente entonces debes usar useComputed y no es necesario hacer un seguimiento explícito y todo es automático. Por otro lado, si no estás realmente produciendo un valor sino que quieres crear un efecto secundario que ocurre fuera del sistema entonces probablemente será asíncrono. Y si lo haces, entonces debes hacer un seguimiento. Y hay una tercera forma de verlo que aún no hemos cubierto, pero lo cubriremos pronto es que tal vez quiero obtener un valor pero el valor no se deriva del estado actual sino que realmente tengo que ir a un estado externo.
19. Uso de Recursos y Obtención de Datos
Short description:
La función useResource se utiliza para operaciones asíncronas y requiere un seguimiento explícito. Permite efectos secundarios fuera del sistema y puede actualizar señales. La función useSyncExternalStore no es familiar y requiere más investigación. Las señales no pueden funcionar con operaciones asíncronas, por lo que es necesario un seguimiento explícito. La función useResource devuelve una promesa con datos. Los puntos finales en Quick se pueden crear utilizando la función useResource. La función useResource se utiliza para obtener datos de un sistema externo y devolverlos. La función obtener lista de usuarios puede ejecutarse en un servidor o en un cliente. La función useResource se utiliza para obtener datos de la API de GitHub y devolver una lista de usuarios. El recurso de usuario se puede renderizar y actualizar con la función useResource.
Entonces eso es un uso de recurso. Y en el caso de uso de recurso, que cubriremos a continuación, porque es asíncrono, también debes usar seguimiento. Básicamente, la cosa del seguimiento es una especie de compromiso entre el hecho de que esta función puede ser asíncrona y también porque esta función no está destinada a, está destinada a efectos secundarios fuera del sistema en lugar de para el sistema en sí, aunque puedes hacer este tipo de trucos donde puedes ir y actualizar la señal nuevamente y hacer que suceda la cosa. Así que esa es una respuesta un poco complicada.
¿Es algo como useSyncExternalStore? Espera, ¿por qué es diferente? De acuerdo, respondí a esta pregunta. ¿Es algo como useSyncExternalStore? No sé qué es useSyncExternalStore. Vaya, está al revés porque estoy en Israel. De acuerdo, espera. Ah, lo siento. De acuerdo. Creo que esto se acerca más a un recurso que vamos a cubrir a continuación. De acuerdo. En realidad, necesito leer más sobre esto. No estoy familiarizado con esta API, así que es un buen aprendizaje para mí.
De acuerdo, entonces las funciones de seguimiento, básicamente cuando tienes asincronía, debido a cómo funcionan las señales, las señales no pueden funcionar con operaciones asíncronas, por lo que necesitas una función de seguimiento explícito. O más bien, sería muy confuso si tuviera que explicar el hecho de que, oh, si tienes async, entonces la señal solo funcionará antes del await, pero no después del await. Y el problema es que sería muy tentador que alguien más insertara un await en algún lugar, y básicamente podrían romper la reactividad. Y por este motivo, con async requerimos que hagas un seguimiento, y volviendo al useComputed, esto es, cuando haces async, en realidad estás devolviendo una promesa con cosas.
Oh, aquí debería haber un error, necesito arreglar esto. Esto es un error, debería ser un error, porque esto no debería permitirte lidiar con async por esa razón específica. De acuerdo. De acuerdo, lo tenemos aquí. Aquí tenemos una memoria, hacemos una actualización. Y ahora... Oh, cierto, ¿cuál es la siguiente cosa que quiero hacer? Así que, después de un tiempo de debounce, en realidad nos gustaría ir y consultar el servidor. Y así se utiliza un cargador de ruta en la navegación inicial. Y cuando escribimos aquí, no queremos causar una actualización de toda la página, ¿verdad? Solo queremos hablar con el servidor. Así que en ese sentido, queremos hacer una llamada RPC o un punto final y hay una forma sencilla de hacer puntos finales en Quick. Primero que nada, puedes hacer un punto final como te mostré en este ejemplo, ¿verdad? Que puedes hacer get, pero en realidad hay una forma más sencilla de hacerlo. Así que creemos un recurso. Entonces vamos a decir que quiero obtener usuarios y los usuarios serán useResource. Así que useResource es como useTask, pero devuelve un valor, devuelve una señal aquí mismo. Y así tendremos que hacer un seguimiento de esto. Así que vamos a decir const usuario es igual a hacer un seguimiento de la ruta de usuario. Perfecto. Básicamente queremos decir que cada vez que el valor del debounce cambie, nos gustaría devolver y analizar un array vacío. Y así actualizaremos, bueno, en realidad podría ser como console log usuarios usuarios. Y sí, de acuerdo. Así que ahora en realidad puedo hacer trampa y simplemente seguir devolviendo un usuario por ahora. Así que ahora lo que tenemos es nuevamente, no se ejecuta JavaScript en la carga inicial de la página. Lo siento, quiero decir solo JavaScript. No JavaScript. Luego, cuando escribo mi nombre de usuario, medio segundo después, esto se actualiza y quiero que el recurso, bien, en realidad podría ser como console log usuarios usuarios. Y sí, de acuerdo. ¿Así que soy genial? Y luego, medio segundo después, ves que dice usuarios, la promesa se cumple y contiene una matriz de datos, ¿verdad? Así que por ahora solo contiene mi nombre aquí. Pero lo que realmente me gustaría hacer aquí es hablar con un sistema externo para ir a buscar algunos datos para nosotros y luego devolverlos así. Así que creemos una función para eso. Así que digamos que tenemos una función llamada obtener lista de usuarios. Y por ahora, digamos que solo decimos usuarios aquí. Lo siento, usuario más bien, va a ser consulta. Y por ahora, solo vamos a decir obtener lista de usuarios consulta. Y así aquí, y luego vamos a devolver, solo vamos a hacer trampa y devolver la consulta por ahora. Y así en lugar de hacer todo esto, podemos simplemente decir return obtener lista de usuarios. Oops. ¿Y por qué no estás contento? De acuerdo. Así que esta función se ejecuta y solo hace un console log, ¿verdad? El mismo comportamiento exacto. Así que tenemos que escribir mheri y luego medio segundo después, tenemos nuestra obtener lista de usuarios para mheri que se ejecuta aquí, ¿verdad? Así que nada de esto es realmente sorprendente, pero hagamos algo que sí lo sea. En realidad, esperemos aquí. En lugar de que esta función se ejecute en un cliente, puedo hacer que esta función se ejecute en un servidor simplemente envolviéndola en un signo de dólar de servidor. Y así, básicamente he creado un punto final. Así que ahora cuando escribo mheri, medio segundo después, nota que obtengo una respuesta, los usuarios, pero en realidad se ejecutó en un servidor. Así que esta función se está ejecutando ahora en un servidor y vamos a hacer un truco más, que es que no queremos ejecutarlo cuando esté vacío. En realidad, así que si, lo siento, const, sí, un valor, y luego si consulta, entonces entra aquí, de lo contrario, devuelve un array vacío. Así que ahora no se ejecuta en un servidor y cuando escribo algo, la obtener lista de usuarios se ejecuta en el servidor y así porque estamos en un servidor ahora podemos simplemente ir y hablar con GitHub. Como es una función, lo siento, cambiémoslo a una función. Esto es una función, podemos pasar esto, y esto es un evento de solicitud. Y ahora, ¿por qué se queja? En cualquier momento, y mientras tenga algo, él es el único que se queja. ¿Quién es el que se queja? Porque no es, lo siento, podemos simplemente usar influencia para el truco. Entonces, esto es una solicitud de pest-based, no una solicitud, ¿de acuerdo? Así que vamos a, vamos a, así que la diferencia entre useTask y useResource es que useResource puede devolver datos. Sí, eso es incorrecto. Bueno, esa es una de las diferencias. También hay otra diferencia. Solo puedes tener una useTask ejecutándose a la vez. Por lo tanto, las usedTasks están garantizadas para ejecutarse de forma síncrona, mientras que useResource está destinada a obtener datos externamente y, como resultado, puedes tener múltiples useResources ejecutándose simultáneamente. Por lo tanto, también hay una diferencia de concurrencia entre ellos.
20. Obtención de Datos del Servidor y Renderizado
Short description:
Obtención de datos del servidor y renderizado. El recurso es un conjunto de usuarios obtenidos del servidor. La función se ejecuta en el servidor y devuelve el conjunto de usuarios. El recurso es una promesa que muestra un indicador de carga mientras se obtienen los datos y el conjunto de usuarios una vez resuelto. La función está vinculada al servidor y toma una consulta como argumento. Fluye naturalmente con la información de tipo y maneja los valores nulos. El ejemplo muestra conceptos como el uso de tareas para el debouncing, el uso de recursos para obtener datos del servidor, el renderizado con indicadores de carga y la vinculación de funciones al servidor.
Pero sí, esa es una observación correcta. Así que, obteniendo data del servidor. Así que voy a obtener el tipo. Y eso es... Y así, en nuestro servidor data, podemos ahora, esto podría ser en un sincronismo, vamos a hacer una consulta, vamos a hablar con GitHub, pasarle su token de acceso. Observa, nuevamente, porque ahora estamos ejecutando en un servidor, tenemos acceso al entorno y podemos pasar un token de acceso. Y obtenemos una lista de usuarios y simplemente la devolvemos. Y como podemos devolver esto, ahora observa que el recurso de usuario tiene un tipo correcto. Así que ahora, nuestro recurso de usuario es correcto.
Y lo siguiente que debemos hacer es renderizarlo. Así que simplemente hacemos un recurso. Solo sí, importar. Los valores son usuarios. Y digo en pendiente. Decimos cargando. Y resuelto. en... De acuerdo, así que ahora para los usuarios, hacemos usuarios, no math. Hola. La línea de comandos. De acuerdo. Así que en la lista no ordenada, rehacer. Elemento de usuarios. Hay elementos. Oh, elementos. No, es un array. Así que los elementos son un array. ¿Por qué te quejas? Oh, porque, ok, lo siento porque este tipo podría ser un array vacío, pero es un array vacío. Así que está, de acuerdo. Oh. Usuarios es un objeto que tiene elementos, así que ¿por qué te quejas de eso? Oh, oh. Oh, cierto, cierto, cierto, cierto. Oh, de acuerdo. Así que esto me da usuarios, que es este objeto de usuarios. Bien. Así que esto nos da usuarios. Así que este es el final de usuarios. Aquí vamos. De acuerdo. Muy bien. De acuerdo. Así que ahora podemos escribir en la consulta. Y obtenemos una lista, así que observa lo que está sucediendo. Escribimos y hay un retraso de cinco milisegundos para actualizar. Una vez que esto se actualiza, el recurso se vuelve a ejecutar porque el recurso requiere una clave privada. En realidad, estamos ejecutando el componente en el servidor. Y así, en un servidor, no son los componentes los que obtienen la lista de usuarios, en realidad se ejecutan en el servidor. Esto obtiene nuestros data devuelve el conjunto que necesitamos y luego obtenemos el recurso de los usuarios. Y luego el recurso es esencialmente una promesa. Y así, cuando la promesa está en estado pendiente, imprimimos cargando, de lo contrario imprimimos un conjunto de usuarios. Así que si escribo verás que mostrará cargando durante un segundo y mostrará un conjunto de usuarios asociados a la lista. Ahora esto debería ser clickable, así que arreglemos eso. Ahora puedo hacer clic en él y simplemente navegar a la siguiente página. Puedes ver que puedo ver una lista de cosas.
De acuerdo. Así que esto es un concepto advanced porque, ya sabes, pude mostrarte cómo, podemos, bueno, repasemos, ¿verdad? Tenemos un componente, el componente, esto solo mostraba que el renderizado no se realiza o se vuelve a renderizar en el cliente de manera ansiosa, lo hace de manera perezosa. Obtenemos una lista de favoritos, que obtenemos de Superbase. Luego obtenemos un usuario que está vinculado a la entrada. Luego creamos un selector de debouncing, que tiene un retraso. Esta es la forma más complicada de escribirlo, creo que había una forma más sencilla antes, antes de que lo refactorizáramos. Luego decimos, genial, ahora necesitamos un recurso. El recurso es un conjunto de usuarios. Y así miramos la consulta. Si tenemos una consulta, entonces vamos a hablar con el servidor, de lo contrario estamos en nulo. Sabemos que estamos hablando con el servidor porque esta función está, ¿dónde está? Aquí, tiene un signo de dólar de servidor alrededor. El signo de dólar de servidor se asegurará de que esta función siempre se ejecute en un servidor. En esencia, hemos creado un punto final con el que podemos hablar y esencialmente una llamada RPC sin tener que preocuparnos por cómo serializar las cosas. Ahora esto es útil para muchas cosas, pero solo quiero señalar que todavía hay un momento y un lugar para algo como TRPC donde quieres tener un control total sobre la respuesta, quieres asegurarte de que las versiones sean estables u otras cosas. Así que esto no es solo un reemplazo total, pero en muchos casos esto es suficiente. Esta es una forma simple y fácil de hacerlo. Así que básicamente dice, asegúrate de que esta función se ejecute en un servidor. Como es una función, podemos tomar un parámetro de consulta, ¿verdad? En el servidor, tenemos acceso a variables de entorno. Así que podemos obtener la variable de entorno aquí y simplemente hacer una solicitud fetch al servidor. Usamos nuestro actualmente conectado. ¿Tenemos que usar? No, básicamente obtenemos un conjunto de elementos y lo devolvemos, ¿verdad? Así que ahora el repositorio devuelve el conjunto de usuarios aquí. Esto hace que el recurso elimine el indicador de carga y lo reemplace con un UL. Este UL ahora tiene una lista de LIs que provienen del servidor, y simplemente lo mapeamos y creamos una lista. Así que esto muestra muchos conceptos interesantes como el uso de tareas para el debouncing, muestra el uso de recursos para obtener data del servidor. Muestra una forma de renderizar cosas, muestra un indicador de carga mientras se obtienen los data del servidor. Y mostramos cómo vincular una función al servidor. Observa que esta función devuelve un tipo específico. Y así la función devuelve un tipo específico. Además, muestra que toma una consulta como argumento, ¿verdad? Dondequiera que se use esta función, si olvido llamarla con una consulta, observa que se queja para asegurarnos de que la tengamos. Pero también la información de tipo fluye correctamente aquí y si paso el cursor sobre usuario, puedo ver que este es un objeto del tipo correcto o nulo en caso de que no haya consulta. Así que toda la información de tipo fluye naturalmente sin que tengas que configurar nada. Es una forma muy, muy natural de hacerlo. De acuerdo, alguien está preguntando, ¿podemos usar Lodash para debouncear una lista de usuarios?
21. Uso de la Función Debounce
Short description:
Sí, definitivamente podrías usar la función debounce de lodash. Solo asegúrate de ejecutar el código necesario para el seguimiento antes de llamar a debounce.
Creo que sí. Veamos. Es una buena pregunta. Entonces, ¿lodash debounce? La función debounce tiene 8 opciones para su uso. Sí, ejecuta esta función. Ejecuta esta función. Sí. Oh, pero tendrías que pasar un argumento diferente, no, eso también estaría bien. Sí, definitivamente podrías usar debounce. Lo único que tendrías que hacer es asegurarte de que en algún lugar de tu tarea se llame a este fragmento de código aquí. ¿Verdad? Entonces este fragmento de código tendría que ejecutarse para que ocurra el seguimiento pero una vez que el seguimiento esté ocurriendo, puedes llamar a debounce sin problema, y esta API debería funcionar con lodash.
22. Integración de CMS sin cabeza y Componentes Personalizados
Short description:
En esta última parte, integramos nuestro CMS visual sin cabeza y demostramos sus características. Mostramos cómo agregar imágenes, personalizar componentes y permitir que el departamento de marketing modifique el contenido. También mencionamos la disponibilidad de lecciones sobre implementación en Cloudflare. Si tienen alguna pregunta, no duden en preguntar.
De acuerdo. Así que nos quedan unos 10 minutos. Voy a mostrarte una cosa más y podemos dar por terminado. Obviamente, sigue haciendo preguntas. Si tienes otras preguntas, avísame. Me encantaría responderlas.
De acuerdo. Voy a mostrarte cómo puedes integrarte con nuestro CMS visual headless. Así que voy a hacer npm. Ejecutar quick. Y voy a decir que quiero integrarlo con VictorIO. Reinicia el servidor. Aquí hay una ruta predeterminada, que es esta index. Y voy a dejar esta ruta predeterminada. Y eso es porque cuando ejecutamos la integración de Builder IO, creó una ruta de captura de todo, que está aquí. Básicamente, cómo funciona esto es que si algo coincide con una de las rutas existentes, entonces usamos una ruta existente. Si no se captura ninguna ruta existente, entonces vamos a la index, esta ruta es la que se capturará. Ahora esto requiere la clave pública de Builder. Ya lo he configurado en la variable de entorno, al igual que las otras claves públicas. Y así que si lo hicimos bien. Veamos. Echemos un vistazo. Ahí está un saludo del CMS. Vamos a ir a esto, esto, porque ya estoy conectado aquí. Y lo que quiero mostrarte es que esto es una integración. Ups, aquí. Esta sección aquí, fíjate que dice que necesito iniciar sesión. Así que noto que esta sección aquí no está iniciada, ¿verdad? Así que este encabezado claramente proviene del diseño. De acuerdo. Esto va bien. Esto proviene del diseño, pero si hago clic en nuestro editor, esto nos llevará a nuestro editor. Ahora, obviamente ya configuré nuestro editor con el contenido. Así que ya lo teníamos, pero lo que quiero mostrarte es que tú sabes, el, el, el, el diseño se activó, ¿verdad? Así que el cierre de sesión está aquí y el pie de página también se muestra aquí y aquí, eso está usando la URL incorrecta. Así que vamos a cambiar esto a nuestra URL local. Y ahora ves que tenemos nuestra página. Tenemos nuestra página. De acuerdo, tenemos nuestro CMS que ya está integrado, y este CMS, puedo ir y, por ejemplo, decir, hey, me gustaría poner una imagen aquí. Así que ahora imagina que has integrado algo como esto con tu departamento de marketing, y luego el departamento de marketing es libre de modificar cosas. Digamos que quieren una imagen. Solo voy a elegir una foto de archivo. Esta se ve bien. Y voy a colocar una nueva hoja en el centro, pero eso es demasiado grande. Así que vamos a ir a Estilos. Y el ancho máximo, hagámoslo 100 píxeles. ¿De acuerdo? Así puedo hacer esto. Puedo hacer clic en publicar. Y tarda uno o dos minutos en propagarse a través de nuestro, tarda un minuto o dos en propagarse a través de nuestro CDN. Pero en pocos segundos, deberíamos ver que nuestra imagen se ha mostrado. Ahí está. Ahí está. Y lo bueno es que el departamento de marketing puede ir y modificar cualquier cosa que deseen que esté aquí. Pero quiero mostrarte algo más, una cosa genial más, y creo que se nos acaba el tiempo y eso es, tenemos componentes personalizados. Y así que lo que podemos hacer aquí es declarar un nuevo componente personalizado. Ups. Voy a llamarlo búsqueda. Y el componente de búsqueda. De acuerdo. Bien. Espera. De acuerdo. Así que voy a tomar este componente de búsqueda aquí. Lo voy a mover a un componente separado llamado búsqueda. Y el componente de búsqueda básicamente necesita todo esto. Entonces root favorite necesita una señal. Eval tres source, y no necesita esto, de acuerdo. De acuerdo. Así que acabamos de refactorizar el componente de búsqueda en algo separado, ¿verdad? Ups, de acuerdo. El componente de búsqueda ahora está definido. Entonces... Entonces, búsqueda importada, desde la ruta, sí. Y llamémoslo búsqueda, no nos preocupemos por los inputs. Y así, ahora que lo hemos registrado aquí... De acuerdo, lo que el departamento de marketing puede hacer es, pueden decir, fíjate que, ahí está nuestro componente de búsqueda, y puedo arrastrar el componente de búsqueda, pongámoslo debajo de la imagen. Y publicado. Y ahora, lo siento, eso no es el... Así que esperemos a que el CDN se propague. Y así, ahora el departamento de marketing pudo usar un componente existente que pudieron arrastrar y soltar en la salida, y puedes ver que la salida aparece. Así que podemos decir quién está interesado en QUIC, y puedes ver diferentes usuarios que tienen QUIC en su nombre. Y así, ahora el departamento de marketing es libre de editar cualquier, bueno, no cualquier parte, ¿verdad?, no pueden editar el botón de inicio de sesión eso no está disponible para ellos. Y ciertamente no pueden editar el pie de página eso no está disponible para ellos. Pero este componente aquí en realidad es interactivo, podemos escribir, supongo que no pueden escribir. Pero pudieron arrastrar y soltar estos componentes personalizados. Entonces, puedes crear tus propios componentes personalizados para el editor. De acuerdo, voy a detenerme aquí, porque creo que hemos cubierto mucho, y avísame si hay alguna pregunta. Quiero señalar que todo lo que hemos hecho está disponible para ti dentro de estas lecciones aquí. Hay otra lección que no hemos tenido la oportunidad de hacer, pero básicamente muestra cómo adjuntar Cloudflare para que puedas implementar fácilmente tu aplicación en Cloudflare para tu interfaz de usuario, etc. Eso es todo, no creo que tengamos nada más al respecto. Así que avísame si tienes otras preguntas. De lo contrario, vamos a dar por terminado el día.
23. Paradigma de Renderizado de Quick y Quickify
Short description:
Quick proporciona un paradigma de renderizado único que hace que cada aplicación sea instantáneamente interactiva. La experiencia del desarrollador es agradable, con formas sencillas de lograr mucho. React-Quickify permite convertir componentes de React en componentes de Quick. Se pueden utilizar componentes existentes, aunque no tienen carga láser. Quickify está disponible para React, solid, Vue, SWAD y Angular.
Espero que lo hayas disfrutado. Gracias por las palabras amables, lo aprecio. Espero que cuando empieces a jugar con Quick, descubras que no solo Quick proporciona un paradigma de renderizado muy único, que hace que cada aplicación sea esencialmente instantáneamente interactiva. Pero también descubrirás que en realidad, la experiencia del desarrollador es muy agradable y puedes lograr muchas cosas con solo, simples pulsaciones de teclas, etc., formas sencillas de expresarte.
¿Está Salajay en la lista de frameworks compatibles? Sí, mencioné que tenemos algo llamado React-Quickify, que no mencioné aquí y debería haberlo hecho. React-Quickify te permite tomar componentes de React y convertirlos en un componente de Quick. Obviamente, no pueden hacer toda esta carga láser elegante, todavía requieren hidratación. Pero el beneficio de esto es que puedes usar componentes existentes. No tenemos un Quickify para solid, pero tenemos miembros de la comunidad que lo han hecho. Entonces, hay una comunidad que ha hecho un Quickify para solid, para Vue, para SWAD y para Angular. El equipo principal de QUIC está apoyando explícitamente el Quickify para React. Gracias por todo tu tiempo.
Los primeros intentos de Ivan en la depuración de rendimiento fueron caóticos. Vería una interacción lenta, intentaría una optimización aleatoria, vería que no ayudaba, y seguiría intentando otras optimizaciones hasta que encontraba la correcta (o se rendía). En aquel entonces, Ivan no sabía cómo usar bien las herramientas de rendimiento. Haría una grabación en Chrome DevTools o React Profiler, la examinaría, intentaría hacer clic en cosas aleatorias, y luego la cerraría frustrado unos minutos después. Ahora, Ivan sabe exactamente dónde y qué buscar. Y en esta masterclass, Ivan te enseñará eso también. Así es como va a funcionar. Tomaremos una aplicación lenta → la depuraremos (usando herramientas como Chrome DevTools, React Profiler, y why-did-you-render) → identificaremos el cuello de botella → y luego repetiremos, varias veces más. No hablaremos de las soluciones (en el 90% de los casos, es simplemente el viejo y regular useMemo() o memo()). Pero hablaremos de todo lo que viene antes - y aprenderemos a analizar cualquier problema de rendimiento de React, paso a paso. (Nota: Esta masterclass es más adecuada para ingenieros que ya están familiarizados con cómo funcionan useMemo() y memo() - pero quieren mejorar en el uso de las herramientas de rendimiento alrededor de React. Además, estaremos cubriendo el rendimiento de la interacción, no la velocidad de carga, por lo que no escucharás una palabra sobre Lighthouse 🤐)
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)
- Introducción- Prerrequisitos para la masterclass- Estrategias de obtención: fundamentos- Estrategias de obtención – práctica: API de obtención, caché (estática VS dinámica), revalidar, suspense (obtención de datos en paralelo)- Prueba tu construcción y sírvela en Vercel- Futuro: Componentes de servidor VS Componentes de cliente- Huevo de pascua de la masterclass (no relacionado con el tema, destacando la accesibilidad)- Conclusión
Los primeros intentos de Ivan en la depuración de rendimiento fueron caóticos. Veía una interacción lenta, probaba una optimización aleatoria, veía que no ayudaba, y seguía probando otras optimizaciones hasta que encontraba la correcta (o se rendía). En aquel entonces, Ivan no sabía cómo usar bien las herramientas de rendimiento. Hacía una grabación en Chrome DevTools o React Profiler, la examinaba, intentaba hacer clic en cosas al azar, y luego la cerraba frustrado unos minutos después. Ahora, Ivan sabe exactamente dónde y qué buscar. Y en esta masterclass, Ivan te enseñará eso también. Así es como va a funcionar. Tomaremos una aplicación lenta → la depuraremos (usando herramientas como Chrome DevTools, React Profiler, y why-did-you-render) → identificaremos el cuello de botella → y luego repetiremos, varias veces más. No hablaremos de las soluciones (en el 90% de los casos, es simplemente el viejo y regular useMemo() o memo()). Pero hablaremos de todo lo que viene antes - y aprenderemos cómo analizar cualquier problema de rendimiento de React, paso a paso. (Nota: Esta masterclass es más adecuada para ingenieros que ya están familiarizados con cómo funcionan useMemo() y memo() - pero quieren mejorar en el uso de las herramientas de rendimiento alrededor de React. Además, cubriremos el rendimiento de interacción, no la velocidad de carga, por lo que no escucharás una palabra sobre Lighthouse 🤐)
Next.js es un marco convincente que facilita muchas tareas al proporcionar muchas soluciones listas para usar. Pero tan pronto como nuestra aplicación necesita escalar, es esencial mantener un alto rendimiento sin comprometer el mantenimiento y los costos del servidor. En este masterclass, veremos cómo analizar el rendimiento de Next.js, el uso de recursos, cómo escalarlo y cómo tomar las decisiones correctas al escribir la arquitectura de la aplicación.
Acabas de llegar a una página web y tratas de hacer clic en un elemento en particular, pero justo antes de hacerlo, se carga un anuncio encima y terminas haciendo clic en eso en su lugar. Eso... eso es un cambio de diseño. Todos, tanto los desarrolladores como los usuarios, saben que los cambios de diseño son malos. Y cuanto más tarde ocurran, más interrupciones causarán a los usuarios. En este masterclass vamos a analizar cómo las fuentes web causan cambios de diseño y explorar algunas estrategias para cargar fuentes web sin causar grandes cambios de diseño. Tabla de contenidos:¿Qué es CLS y cómo se calcula?¿Cómo las fuentes pueden causar CLS?Estrategias de carga de fuentes para minimizar CLSRecapitulación y conclusión
This transcription provides a brief guide to React rendering behavior. It explains the process of rendering, comparing new and old elements, and the importance of pure rendering without side effects. It also covers topics such as batching and double rendering, optimizing rendering and using context and Redux in React. Overall, it offers valuable insights for developers looking to understand and optimize React rendering.
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.
Mishko, the creator of Angular and AngularJS, discusses the challenges of website performance and JavaScript hydration. He explains the differences between client-side and server-side rendering and introduces Quik as a solution for efficient component hydration. Mishko demonstrates examples of state management and intercommunication using Quik. He highlights the performance benefits of using Quik with React and emphasizes the importance of reducing JavaScript size for better performance. Finally, he mentions the use of QUIC in both MPA and SPA applications for improved startup performance.
The Talk discusses the shift to full-stack frameworks and the challenges of full-stack documentation. It highlights the power of interactive tutorials and the importance of user testing in software development. The Talk also introduces learn.svelte.dev, a platform for learning full-stack tools, and discusses the roadmap for SvelteKit and its documentation.
React 18's concurrent rendering, specifically the useTransition hook, optimizes app performance by allowing non-urgent updates to be processed without freezing the UI. However, there are drawbacks such as longer processing time for non-urgent updates and increased CPU usage. The useTransition hook works similarly to throttling or bouncing, making it useful for addressing performance issues caused by multiple small components. Libraries like React Query may require the use of alternative APIs to handle urgent and non-urgent updates effectively.
Suspense is a mechanism for orchestrating asynchronous state changes in JavaScript frameworks. It ensures async consistency in UIs and helps avoid trust erosion and inconsistencies. Suspense boundaries are used to hoist data fetching and create consistency zones based on the user interface. They can handle loading states of multiple resources and control state loading in applications. Suspense can be used for transitions, providing a smoother user experience and allowing prioritization of important content.
Comments