Agregar funcionalidad dinámica y asíncrona a los sitios JAMstack
Publicado: 2022-03-10¿Significa eso que los sitios JAMstack no pueden manejar interacciones dinámicas? ¡Definitivamente no!
Los sitios JAMstack son excelentes para crear interacciones asincrónicas altamente dinámicas. ¡Con algunos pequeños ajustes en la forma en que pensamos sobre nuestro código, podemos crear interacciones divertidas y envolventes utilizando solo activos estáticos!
Cada vez es más común ver sitios web creados con JAMstack, es decir, sitios web que se pueden servir como archivos HTML estáticos creados a partir de JavaScript, Markup y API. A las empresas les encanta JAMstack porque reduce los costos de infraestructura, acelera la entrega y reduce las barreras para mejorar el rendimiento y la seguridad porque el envío de activos estáticos elimina la necesidad de escalar servidores o mantener las bases de datos altamente disponibles (lo que también significa que no hay servidores o bases de datos que puedan ser hackeado). A los desarrolladores les gusta JAMstack porque reduce la complejidad de tener un sitio web en vivo en Internet: no hay servidores para administrar o implementar; podemos escribir código front-end y simplemente se activa , como magia .
("Magic" en este caso son implementaciones estáticas automatizadas, que están disponibles de forma gratuita en varias empresas, incluida Netlify, donde trabajo).
Pero si pasa mucho tiempo hablando con los desarrolladores sobre JAMstack, surgirá la pregunta de si JAMstack puede o no manejar aplicaciones web serias. Después de todo, los sitios JAMstack son sitios estáticos, ¿verdad? ¿Y los sitios estáticos no están muy limitados en lo que pueden hacer?
Este es un concepto erróneo muy común, y en este artículo vamos a profundizar en el origen del concepto erróneo, analizar las capacidades de JAMstack y analizar varios ejemplos del uso de JAMstack para crear aplicaciones web serias.
Fundamentos de JAMstack
Phil Hawksworth explica qué significa realmente JAMStack y cuándo tiene sentido usarlo en sus proyectos, además de cómo afecta las herramientas y la arquitectura de front-end. Leer un artículo relacionado →
¿Qué hace que un sitio JAMstack sea "estático"?
Los navegadores web actuales cargan archivos HTML, CSS y JavaScript, tal como lo hacían en los años 90.
Un sitio JAMstack, en esencia, es una carpeta llena de archivos HTML, CSS y JavaScript.
Estos son "activos estáticos", lo que significa que no necesitamos un paso intermedio para generarlos (por ejemplo, los proyectos de PHP como WordPress necesitan un servidor para generar el HTML en cada solicitud).
Ese es el verdadero poder de JAMstack: no requiere ninguna infraestructura especializada para funcionar. Puede ejecutar un sitio JAMstack en su computadora local, colocándolo en su red de entrega de contenido (CDN) preferida, alojándolo con servicios como GitHub Pages; incluso puede arrastrar y soltar la carpeta en su cliente FTP favorito para cargarlo. al alojamiento compartido.
Los activos estáticos no significan necesariamente experiencias estáticas
Debido a que los sitios JAMstack están hechos de archivos estáticos, es fácil suponer que la experiencia en esos sitios es estática . ¡Pero ese no es el caso!
JavaScript es capaz de hacer un montón de cosas dinámicas. Después de todo, los marcos de JavaScript modernos son archivos estáticos después de que pasamos por el paso de compilación, y hay cientos de ejemplos de experiencias de sitios web increíblemente dinámicas impulsadas por ellos.
Existe una idea errónea común de que "estático" significa inflexible o fijo. Pero todo lo que "estático" realmente significa en el contexto de "sitios estáticos" es que los navegadores no necesitan ninguna ayuda para entregar su contenido: pueden usarlo de forma nativa sin que un servidor maneje un paso de procesamiento primero.
O, dicho de otra manera:
“Activos estáticos” no significa aplicaciones estáticas; significa que no se requiere servidor.
“
¿Puede el JAMstack hacer eso?
Si alguien pregunta sobre la creación de una nueva aplicación, es común ver sugerencias para enfoques de JAMstack como Gatsby, Eleventy, Nuxt y otras herramientas similares. Es igualmente común ver surgir objeciones: “los generadores de sitios estáticos no pueden hacer _______”, donde _______ es algo dinámico.
Pero, como mencionamos en la sección anterior, ¡los sitios JAMstack pueden manejar contenido dinámico e interacciones!
Aquí hay una lista incompleta de cosas que he escuchado repetidamente que la gente afirma que JAMstack no puede manejar y que definitivamente puede:
- Cargar datos de forma asíncrona
- Manejar archivos de procesamiento, como la manipulación de imágenes.
- Leer y escribir en una base de datos
- Maneje la autenticación del usuario y proteja el contenido detrás de un inicio de sesión
En las siguientes secciones, veremos cómo implementar cada uno de estos flujos de trabajo en un sitio JAMstack.
Si no puede esperar para ver el JAMstack dinámico en acción, primero puede ver las demostraciones, luego regresar y aprender cómo funcionan.
Una nota sobre las demostraciones :
Estas demostraciones están escritas sin marcos. Son solo HTML, CSS y JavaScript estándar. Se crearon teniendo en cuenta los navegadores modernos (p. ej., Chrome, Firefox, Safari, Edge) y aprovechan las funciones más nuevas, como los módulos de JavaScript, las plantillas HTML y la API Fetch. No se agregaron polyfills, por lo que si está utilizando un navegador no compatible, las demostraciones probablemente fallarán.
Cargar datos desde una API de terceros de forma asíncrona
"¿Qué pasa si necesito obtener nuevos datos después de que se creen mis archivos estáticos?"
En JAMstack, podemos aprovechar numerosas bibliotecas de solicitudes asincrónicas, incluida la API Fetch integrada, para cargar datos mediante JavaScript en cualquier momento.
Demostración: busque una API de terceros desde un sitio JAMstack
Un escenario común que requiere carga asíncrona es cuando el contenido que necesitamos depende de la entrada del usuario. Por ejemplo, si creamos una página de búsqueda para la API de Rick & Morty , no sabemos qué contenido mostrar hasta que alguien haya ingresado un término de búsqueda.
Para manejar eso, necesitamos:
- Cree un formulario donde las personas puedan escribir su término de búsqueda,
- Escuche el envío de un formulario,
- Obtenga el término de búsqueda del envío del formulario,
- Envíe una solicitud asíncrona a la API de Rick & Morty utilizando el término de búsqueda,
- Mostrar los resultados de la solicitud en la página.
Primero, necesitamos crear un formulario y un elemento vacío que contendrá nuestros resultados de búsqueda, que se ve así:
<form> <label for="name">Find characters by name</label> <input type="text" name="name" required /> <button type="submit">Search</button> </form> <ul></ul>
A continuación, debemos escribir una función que maneje los envíos de formularios. Esta función:
- Evitar el comportamiento predeterminado de envío de formularios
- Obtenga el término de búsqueda de la entrada del formulario
- Use la API Fetch para enviar una solicitud a la API de Rick & Morty usando el término de búsqueda
- Llame a una función de ayuda que muestra los resultados de la búsqueda en la página
También necesitamos agregar un detector de eventos en el formulario para el evento de envío que llama a nuestra función de controlador.
Así es como se ve ese código en conjunto:
<script type="module"> import showResults from './show-results.js'; const form = document.querySelector('form'); const handleSubmit = async event => { event.preventDefault(); // get the search term from the form input const name = form.elements['name'].value; // send a request to the Rick & Morty API based on the user input const characters = await fetch( `https://rickandmortyapi.com/api/character/?name=${name}`, ) .then(response => response.json()) .catch(error => console.error(error)); // add the search results to the DOM showResults(characters.results); }; form.addEventListener('submit', handleSubmit); </script>
Nota: para mantener el enfoque en los comportamientos dinámicos de JAMstack, no discutiremos cómo se escriben las funciones de utilidad como showResults. Sin embargo, el código está completamente comentado, ¡así que echa un vistazo a la fuente para saber cómo funciona!
Con este código en su lugar, podemos cargar nuestro sitio en un navegador y veremos el formulario vacío sin mostrar resultados:
Si ingresamos el nombre de un personaje (por ejemplo, "rick") y hacemos clic en "buscar", vemos una lista de personajes cuyos nombres contienen "rick":
¡Oye! ¿Ese sitio estático simplemente cargó datos dinámicamente? ¡Santos baldes!
Puede probarlo usted mismo en la demostración en vivo o consultar el código fuente completo para obtener más detalles.
Manejar tareas informáticas costosas fuera del dispositivo del usuario
En muchas aplicaciones, necesitamos hacer cosas que requieren muchos recursos, como procesar una imagen. Si bien algunos de estos tipos de operaciones son posibles solo con JavaScript del lado del cliente, no es necesariamente una buena idea hacer que los dispositivos de sus usuarios hagan todo ese trabajo. Si están en un dispositivo de baja potencia o están tratando de estirar el último 5% de la vida útil de la batería, hacer que su dispositivo haga mucho trabajo probablemente sea una experiencia frustrante para ellos.
Entonces, ¿eso significa que las aplicaciones JAMstack no tienen suerte? ¡Para nada!
La "A" en JAMstack significa API. Esto significa que podemos enviar ese trabajo a una API y evitar hacer girar los ventiladores de las computadoras de nuestros usuarios hasta la configuración de "desplazamiento".
“Pero espera”, podrías decir. "Si nuestra aplicación necesita hacer un trabajo personalizado, y ese trabajo requiere una API, ¿no significa eso solo que estamos construyendo un servidor?"
Gracias al poder de las funciones sin servidor, ¡no tenemos que hacerlo!
Las funciones sin servidor (también llamadas "funciones lambda") son una especie de API que no requiere ningún tipo de repetitivo de servidor. Podemos escribir una función de JavaScript simple y antigua, y todo el trabajo de implementación, escalado, enrutamiento, etc., se descarga en nuestro proveedor sin servidor de elección.
El uso de funciones sin servidor no significa que no haya un servidor; simplemente significa que no necesitamos pensar en un servidor.
“
Las funciones sin servidor son la mantequilla de maní para nuestro JAMstack: desbloquean todo un mundo de funcionalidad dinámica y de alta potencia sin pedirnos que nos ocupemos del código del servidor o devops.
Demostración: convertir una imagen a escala de grises
Supongamos que tenemos una aplicación que necesita:
- Descargar una imagen desde una URL
- Convierte esa imagen a escala de grises
- Cargue la imagen convertida en un repositorio de GitHub
Hasta donde yo sé, no hay forma de hacer conversiones de imágenes como esa completamente en el navegador, e incluso si la hubiera, es algo que requiere muchos recursos, por lo que probablemente no queramos poner esa carga en nuestros usuarios. ' dispositivos.
En su lugar, podemos enviar la URL para que se convierta en una función sin servidor, que hará el trabajo pesado por nosotros y devolverá una URL a una imagen convertida.
Para nuestra función sin servidor, usaremos Netlify Functions. En el código de nuestro sitio, agregamos una carpeta en el nivel raíz llamada "funciones" y creamos un nuevo archivo llamado "convert-image.js" dentro. Luego, escribimos lo que se llama un controlador, que es lo que recibe y, como habrás adivinado, maneja las solicitudes a nuestra función sin servidor.
Para convertir una imagen, se ve así:
exports.handler = async event => { // only try to handle POST requests if (event.httpMethod !== 'POST') { return { statusCode: 404, body: '404 Not Found' }; } try { // get the image URL from the POST submission const { imageURL } = JSON.parse(event.body); // use a temporary directory to avoid intermediate file cruft // see https://www.npmjs.com/package/tmp const tmpDir = tmp.dirSync(); const convertedPath = await convertToGrayscale(imageURL, tmpDir); // upload the processed image to GitHub const response = await uploadToGitHub(convertedPath, tmpDir.name); return { statusCode: 200, body: JSON.stringify({ url: response.data.content.download_url, }), }; } catch (error) { return { statusCode: 500, body: JSON.stringify(error.message), }; } };
Esta función hace lo siguiente:
- Comprueba para asegurarse de que la solicitud se envió mediante el método HTTP POST
- Toma la URL de la imagen del cuerpo POST
- Crea un directorio temporal para almacenar archivos que se limpiarán una vez que la función termine de ejecutarse
- Llama a una función auxiliar que convierte la imagen a escala de grises
- Llama a una función auxiliar que sube la imagen convertida a GitHub
- Devuelve un objeto de respuesta con un código de estado HTTP 200 y la URL de la imagen recién cargada
Nota : no veremos cómo funciona el asistente para la conversión de imágenes o la carga en GitHub, pero el código fuente está bien comentado para que pueda ver cómo funciona.
A continuación, debemos agregar un formulario que se utilizará para enviar las URL para su procesamiento y un lugar para mostrar el antes y el después:
<form action="/.netlify/functions/convert-image" method="POST" > <label for="imageURL">URL of an image to convert</label> <input type="url" name="imageURL" required /> <button type="submit">Convert</button> </form> <div></div>
Finalmente, necesitamos agregar un detector de eventos al formulario para que podamos enviar las URL a nuestra función sin servidor para su procesamiento:
<script type="module"> import showResults from './show-results.js'; const form = document.querySelector('form'); form.addEventListener('submit', event => { event.preventDefault(); // get the image URL from the form const imageURL = form.elements['imageURL'].value; // send the image off for processing const promise = fetch('/.netlify/functions/convert-image', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ imageURL }), }) .then(result => result.json()) .catch(error => console.error(error)); // do the work to show the result on the page showResults(imageURL, promise); }); </script>
Después de implementar el sitio (junto con su nueva carpeta de "funciones") en Netlify y/o iniciar Netlify Dev en nuestra CLI, podemos ver el formulario en nuestro navegador:
Si agregamos una URL de imagen al formulario y hacemos clic en "convertir", veremos "procesando..." por un momento mientras se realiza la conversión, luego veremos la imagen original y su contraparte en escala de grises recién creada:
¡Oh, maldita sea! ¡Nuestro sitio JAMstack acaba de manejar algunos negocios bastante serios y no tuvimos que pensar en los servidores una vez o agotar las baterías de nuestros usuarios!
Use una base de datos para almacenar y recuperar entradas
En muchas aplicaciones, inevitablemente vamos a necesitar la capacidad de guardar la entrada del usuario. Y eso significa que necesitamos una base de datos.
Usted puede estar pensando, “Así que eso es todo, ¿verdad? ¿Se acabó la plantilla? ¡Seguramente un sitio JAMstack, que nos ha dicho que es solo una colección de archivos en una carpeta, no se puede conectar a una base de datos!
Au contraire.
Como vimos en la sección anterior, las funciones sin servidor nos brindan la capacidad de hacer todo tipo de cosas poderosas sin necesidad de crear nuestros propios servidores.
De manera similar, podemos usar herramientas de base de datos como servicio (DBaaS) (como Fauna) para leer y escribir en una base de datos sin tener que configurar una o alojarla nosotros mismos.
Las herramientas DBaaS simplifican enormemente el proceso de configuración de bases de datos para sitios web: crear una nueva base de datos es tan sencillo como definir los tipos de datos que queremos almacenar. Las herramientas generan automáticamente todo el código para administrar las operaciones de creación, lectura, actualización y eliminación (CRUD) y lo ponen a disposición para que lo usemos a través de la API, por lo que no tenemos que administrar una base de datos; solo podemos usarlo .
Demostración: crear una página de petición
Si queremos crear una pequeña aplicación para recopilar firmas digitales para una petición, debemos configurar una base de datos para almacenar esas firmas y permitir que la página las lea para mostrarlas.
Para esta demostración, usaremos Fauna como nuestro proveedor de DBaaS. No profundizaremos en cómo funciona Fauna, pero con el fin de demostrar el pequeño esfuerzo que se requiere para configurar una base de datos, enumeremos cada paso y haga clic para obtener una base de datos lista para usar:
- Crea una cuenta de Fauna en https://fauna.com
- Haga clic en "crear una nueva base de datos"
- Asigne un nombre a la base de datos (por ejemplo, "dynamic-jamstack-demos")
- Haga clic en "crear"
- Haga clic en "seguridad" en el menú de la izquierda en la página siguiente
- Haga clic en "nueva clave"
- Cambie el menú desplegable de roles a "Servidor"
- Agregue un nombre para la clave (por ejemplo, "Dynamic JAMstack Demos")
- Guarde la clave en un lugar seguro para usarla con la aplicación
- Clic en Guardar"
- Haga clic en "GraphQL" en el menú de la izquierda
- Haga clic en "importar esquema"
- Cargue un archivo llamado
db-schema.gql
que contenga el siguiente código:
type Signature { name: String! } type Query { signatures: [Signature!]! }
Una vez que cargamos el esquema, nuestra base de datos está lista para usar. (Seriamente.)
Trece pasos es mucho, pero con esos trece pasos, solo obtuvimos una base de datos, una API GraphQL, administración automática de capacidad, escalado, implementación, seguridad y más, todo manejado por expertos en bases de datos. Gratis. ¡Qué tiempo para estar vivo!
Para probarlo, la opción “GraphQL” del menú de la izquierda nos brinda un explorador GraphQL con documentación sobre las consultas y mutaciones disponibles que nos permiten realizar operaciones CRUD.
Nota : no entraremos en detalles sobre las consultas y mutaciones de GraphQL en esta publicación, pero Eve Porcello escribió una excelente introducción para enviar consultas y mutaciones de GraphQL si desea una introducción a cómo funciona.
Con la base de datos lista para funcionar, podemos crear una función sin servidor que almacene nuevas firmas en la base de datos:
const qs = require('querystring'); const graphql = require('./util/graphql'); exports.handler = async event => { try { // get the signature from the POST data const { signature } = qs.parse(event.body); const ADD_SIGNATURE = ` mutation($signature: String!) { createSignature(data: { name: $signature }) { _id } } `; // store the signature in the database await graphql(ADD_SIGNATURE, { signature }); // send people back to the petition page return { statusCode: 302, headers: { Location: '/03-store-data/', }, // body is unused in 3xx codes, but required in all function responses body: 'redirecting...', }; } catch (error) { return { statusCode: 500, body: JSON.stringify(error.message), }; } };
Esta función hace lo siguiente:
- Toma el valor de la firma de los datos
POST
del formulario - Llama a una función auxiliar que almacena la firma en la base de datos
- Define una mutación de GraphQL para escribir en la base de datos
- Envía la mutación usando una función auxiliar de GraphQL
- Redirige a la página que envió los datos
A continuación, necesitamos una función sin servidor para leer todas las firmas de la base de datos para que podamos mostrar cuántas personas apoyan nuestra petición:
const graphql = require('./util/graphql'); exports.handler = async () => { const { signatures } = await graphql(` query { signatures { data { name } } } `); return { statusCode: 200, body: JSON.stringify(signatures.data), }; };
Esta función envía una consulta y la devuelve.
Una nota importante sobre las claves confidenciales y las aplicaciones JAMstack :
Una cosa a tener en cuenta sobre esta aplicación es que estamos utilizando funciones sin servidor para realizar estas llamadas porque necesitamos pasar una clave de servidor privado a Fauna que demuestre que tenemos acceso de lectura y escritura a esta base de datos. No podemos poner esta clave en el código del lado del cliente, porque eso significaría que cualquiera podría encontrarla en el código fuente y usarla para realizar operaciones CRUD en nuestra base de datos. Las funciones sin servidor son fundamentales para mantener privadas las claves privadas en las aplicaciones JAMstack.
Una vez que hayamos configurado nuestras funciones sin servidor, podemos agregar un formulario que se envíe a la función para agregar una firma, un elemento para mostrar las firmas existentes y un poco de JS para llamar a la función para obtener firmas y ponerlas en nuestra pantalla. elemento:
<form action="/.netlify/functions/add-signature" method="POST"> <label for="signature">Your name</label> <input type="text" name="signature" required /> <button type="submit">Sign</button> </form> <ul class="signatures"></ul> <script> fetch('/.netlify/functions/get-signatures') .then(res => res.json()) .then(names => { const signatures = document.querySelector('.signatures'); names.forEach(({ name }) => { const li = document.createElement('li'); li.innerText = name; signatures.appendChild(li); }); }); </script>
Si cargamos esto en el navegador, veremos nuestro formulario de petición con firmas debajo:
Entonces, si añadimos nuestra firma…
…y envíelo, veremos nuestro nombre adjunto al final de la lista:
¡Perro diggy caliente! ¡Acabamos de escribir una aplicación JAMstack basada en una base de datos completa con aproximadamente 75 líneas de código y 7 líneas de esquema de base de datos!
Proteja el contenido con autenticación de usuario
“Está bien, seguro que esta vez estás atascado”, puedes estar pensando. “No hay forma de que un sitio JAMstack pueda manejar la autenticación de usuarios. ¡¿Cómo diablos funcionaría eso, incluso?!”
Te diré cómo funciona, amigo: con nuestras confiables funciones sin servidor y OAuth.
OAuth es un estándar ampliamente adoptado para permitir que las personas otorguen a las aplicaciones acceso limitado a la información de su cuenta en lugar de compartir sus contraseñas. Si alguna vez ha iniciado sesión en un servicio utilizando otro servicio (por ejemplo, "iniciar sesión con su cuenta de Google"), ha utilizado OAuth anteriormente.
Nota: no profundizaremos en cómo funciona OAuth, pero Aaron Parecki escribió una descripción general sólida de OAuth que cubre los detalles y el flujo de trabajo.
En las aplicaciones JAMstack, podemos aprovechar OAuth y los JSON Web Tokens (JWT) que nos proporciona para identificar a los usuarios, proteger el contenido y permitir que solo los usuarios registrados lo vean.
Demostración: Requerir inicio de sesión para ver contenido protegido
Si necesitamos crear un sitio que solo muestre contenido a los usuarios registrados, necesitamos algunas cosas:
- Un proveedor de identidad que gestiona los usuarios y el flujo de inicio de sesión
- Elementos de la interfaz de usuario para administrar el inicio y cierre de sesión
- Una función sin servidor que busca un usuario conectado usando JWT y devuelve contenido protegido si se proporciona uno
Para este ejemplo, usaremos Netlify Identity, que nos brinda una experiencia de desarrollador realmente agradable para agregar autenticación y proporciona un widget desplegable para administrar las acciones de inicio y cierre de sesión.
Para habilitarlo:
- Visita tu panel de Netlify
- Elija el sitio que necesita autenticación de su lista de sitios
- Haga clic en "identidad" en la parte superior de navegación
- Haga clic en el botón "Habilitar identidad"
Podemos agregar Netlify Identity a nuestro sitio agregando un marcado que muestre el contenido de sesión cerrada y agregue un elemento para mostrar el contenido protegido después de iniciar sesión:
<div class="content logged-out"> <h1>Super Secret Stuff!</h1> <p> only my bestest friends can see this content</p> <button class="login">log in / sign up to be my best friend</button> </div> <div class="content logged-in"> <div class="secret-stuff"></div> <button class="logout">log out</button> </div>
Este marcado se basa en CSS para mostrar contenido en función de si el usuario ha iniciado sesión o no. Sin embargo, no podemos confiar en eso para proteger realmente el contenido: ¡cualquiera podría ver el código fuente y robar nuestros secretos!
En su lugar, creamos un div vacío que contendrá nuestro contenido protegido, pero necesitaremos realizar una solicitud a una función sin servidor para obtener ese contenido. Profundizaremos en cómo funciona eso en breve.
A continuación, debemos agregar código para que nuestro botón de inicio de sesión funcione, cargar el contenido protegido y mostrarlo en la pantalla:
<script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script> <script> const login = document.querySelector('.login'); login.addEventListener('click', () => { netlifyIdentity.open(); }); const logout = document.querySelector('.logout'); logout.addEventListener('click', () => { netlifyIdentity.logout(); }); netlifyIdentity.on('logout', () => { document.querySelector('body').classList.remove('authenticated'); }); netlifyIdentity.on('login', async () => { document.querySelector('body').classList.add('authenticated'); const token = await netlifyIdentity.currentUser().jwt(); const response = await fetch('/.netlify/functions/get-secret-content', { headers: { Authorization: `Bearer ${token}`, }, }).then(res => res.text()); document.querySelector('.secret-stuff').innerHTML = response; }); </script>
Esto es lo que hace este código:
- Carga el widget de Netlify Identity, que es una biblioteca auxiliar que crea un modal de inicio de sesión, maneja el flujo de trabajo de OAuth con Netlify Identity y otorga a nuestra aplicación acceso a la información del usuario que ha iniciado sesión.
- Agrega un detector de eventos al botón de inicio de sesión que activa el modal de inicio de sesión de Netlify Identity para abrir
- Agrega un detector de eventos al botón de cierre de sesión que llama al método de cierre de sesión de Netlify Identity.
- Agrega un controlador de eventos para cerrar sesión para eliminar la clase autenticada al cerrar sesión, lo que oculta el contenido de inicio de sesión y muestra el contenido de cierre de sesión
- Agrega un controlador de eventos para iniciar sesión que:
- Agrega la clase autenticada para mostrar el contenido de inicio de sesión y ocultar el contenido de cierre de sesión
- Toma el JWT del usuario que ha iniciado sesión
- Llama a una función sin servidor para cargar contenido protegido, enviando el JWT en el encabezado de Autorización
- Pone el contenido secreto en el div de cosas secretas para que los usuarios registrados puedan verlo
En este momento, la función sin servidor que llamamos en ese código no existe. Vamos a crearlo con el siguiente código:
exports.handler = async (_event, context) => { try { const { user } = context.clientContext; if (!user) throw new Error('Not Authorized'); return { statusCode: 200, headers: { 'Content-Type': 'text/html', }, body: `
¡Estás invitado, ${user.user_metadata.full_name}!
Si puedes leer esto significa que somos mejores amigos.
Aquí están los detalles secretos para mi fiesta de cumpleaños:
`, }; } atrapar (error) { regreso { código de estado: 401, cuerpo: 'No autorizado', }; } };
jason.af/fiesta
Esta función hace lo siguiente:
- Comprueba si hay un usuario en el argumento de contexto de la función sin servidor
- Lanza un error si no se encuentra ningún usuario
- Devuelve contenido secreto después de asegurarse de que un usuario registrado lo solicitó
Netlify Functions detectará Netlify Identity JWT en los encabezados de Autorización y automáticamente pondrá esa información en contexto. ¡Esto significa que podemos buscar un JWT válido sin necesidad de escribir código para validar JWT!
Cuando cargamos esta página en nuestro navegador, veremos primero la página de cierre de sesión:
Si hacemos clic en el botón para iniciar sesión, veremos el widget de Netlify Identity:
Después de iniciar sesión (o registrarse), podemos ver el contenido protegido:
¡Guau! ¡Acabamos de agregar el inicio de sesión de usuario y el contenido protegido a una aplicación JAMstack!
Qué hacer a continuación
JAMstack es mucho más que "solo sitios estáticos": podemos responder a las interacciones de los usuarios, almacenar datos, manejar la autenticación de usuarios y casi cualquier otra cosa que queramos hacer en un sitio web moderno. ¡Y todo sin necesidad de aprovisionar, configurar o implementar un servidor!
¿Qué quieres construir con JAMstack? ¿Hay algo que todavía no esté convencido de que JAMstack pueda manejar? Me encantaría saberlo. ¡Contáctame en Twitter o en los comentarios!