Más ligero y más rápido: una guía para el Svelte Framework
Publicado: 2022-03-11Las aplicaciones web son cada día más populares. Son un mundo en crecimiento que la gente elige por su simplicidad, velocidad y disponibilidad multiplataforma. Las aplicaciones de una sola página (SPA) han tenido una gran participación en este proceso. Los marcos como Angular, Vue.js y React ayudan a los desarrolladores a brindar la mejor experiencia de usuario en un período corto, lo que permite que el código sea compatible y ampliable. Estas herramientas se han mantenido durante mucho tiempo como las más populares en el campo, con muchas ventajas sobre los paquetes recién creados. Se ha sentido como un oligopolio en el mundo SPA. Sin embargo, un grupo de desarrolladores con visión de futuro que apuntan a este mercado podría ingresar con un competidor serio: Svelte.
Svelte es un nuevo enfoque para construir interfaces de usuario. Profundicemos y exploremos qué lo hace tan nuevo creando un formulario de inicio de sesión común.
Arquitectura
Svelte está diseñado para ser más rápido que cualquier otra biblioteca. Se alcanza cambiando el paso de cargar un marco para construir un DOM virtual. En lugar de usar una herramienta durante el proceso de ejecución, se compila en Vanilla JS en la etapa de creación, por lo que la aplicación no requiere dependencias para iniciarse.
Esbelto | Otras bibliotecas SPA (React, Vue.js, Angular, etc.) |
---|---|
1. Abre un sitio web | 1. Abre un sitio web |
La tabla anterior describe por qué Svelte es un ganador absoluto en rendimiento de inicio. Eso no se obtiene mediante ningún tipo de optimización, sino mediante el uso del compilador de JavaScript del navegador disponible en lugar de un compilador lateral.
Instalación
La instalación de Svelte es increíblemente fácil, lo que hace que su uso sea muy agradable. El primer paso es descargar la plantilla del proyecto:
npx degit sveltejs/template svelte-login-form
Completar el comando anterior significa que tenemos una plantilla de proyecto Svelte. Está vacío por el momento y los paquetes NPM necesarios aún no están instalados. Arreglemos eso.
cd svelte-login-form npm install
Ahora la aplicación está lista para comenzar usando el siguiente comando:
npm run dev
Estructura
Cualquier componente de Svelte puede contener las siguientes secciones:
- Texto
- Estilo
- Plantilla
Veamos el ejemplo en el archivo src/App.svelte
.
<script> export let name; </script> <style> h1 { color: purple; } </style> <h1>{name}</h1>
El código anterior contiene exactamente tres secciones:
etiqueta de secuencia de
script
, que es un bloque de JavaScript opcional con las declaraciones de variables y funciones que deben usarse dentro del componente.etiqueta de
style
, que es otro bloque opcional. Es muy parecido a una etiqueta de estilo HTML común excepto por una diferencia importante. Las reglas descritas dentro de este bloque se aplican únicamente a este componente. Aplicar un estilo a un elementop
no afectará a todos los párrafos de la página. Es fantástico ya que no tiene que inventar nombres de clase y nunca anulará accidentalmente otra regla.El último y único bloque requerido es un bloque de plantilla, en este caso, una etiqueta
h1
. Es una presentación/vista de su componente. Está estrechamente vinculado a los bloques de estilo y secuencia de comandos, ya que determinan cómo se diseñará la vista y cómo se comportará.
Svelte es una biblioteca que intenta llevar la modularidad al juego frontal. Mantiene esa modularidad no solo al separar diferentes componentes sino también al aislar la lógica, la vista y la plantilla.
Volviendo al formulario de inicio de sesión que estamos creando, creemos un nuevo archivo LoginForm.svelte
dentro de la carpeta src
con el siguiente contenido:
<style> form { background: #fff; padding: 50px; width: 250px; height: 400px; display: flex; flex-direction: column; justify-content: center; align-items: center; box-shadow: 0px 20px 14px 8px rgba(0, 0, 0, 0.58); } label { margin: 10px 0; align-self: flex-start; font-weight: 500; } input { border: none; border-bottom: 1px solid #ccc; margin-bottom: 20px; transition: all 300ms ease-in-out; width: 100%; } input:focus { outline: 0; border-bottom: 1px solid #666; } button { margin-top: 20px; background: black; color: white; padding: 10px 0; width: 200px; border-radius: 25px; text-transform: uppercase; font-weight: bold; cursor: pointer; transition: all 300ms ease-in-out; } button:hover { transform: translateY(-2.5px); box-shadow: 0px 1px 10px 0px rgba(0, 0, 0, 0.58); } h1 { margin: 10px 20px 30px 20px; font-size: 40px; } </style> <form> <h1></h1> <label>Email</label> <input name="email" placeholder="[email protected]" /> <label>Password</label> <input name="password" type="password" placeholder="password" /> <button type="submit">Log in </button> </form>
Es un componente de estilo tonto que haremos más inteligente más adelante. Para ver este componente en nuestro sitio, debemos representarlo dentro del componente raíz: App. Vayamos y editemos src/App.svelte
para que se vea así:
<script> import LoginForm from "./LoginForm.svelte"; </script> <style> section { height: 100vh; width: 100%; display: flex; justify-content: center; align-items: center; background: linear-gradient(to right, #cd76e2, #e358ab); } </style> <section> <LoginForm /> </section>
Si todo se ha hecho correctamente y la aplicación aún se está ejecutando, nuestro formulario aparecerá en localhost:5000
. Subamos de nivel nuestras habilidades Svelte haciendo que la forma sea más inteligente.
Ir con estado
Cualquier componente en Svelte puede tener su estado. El estado es una variable especial o un grupo de variables especiales que se pueden usar dentro de la plantilla. ¿Por qué digo "especial"? Cada vez que se cambia una variable de este tipo, la plantilla recibe una notificación al respecto y presenta el contenido con el estado más reciente. Esto permite que la aplicación reaccione a las interacciones del usuario muy rápido.
Declararemos variables de estado de email
y password
donde se almacenarán los valores de formulario para los campos apropiados. Significa que nuestras variables de email
y password
siempre estarán sincronizadas con los valores del formulario, por lo que estaremos listos para enviar estos valores en cualquier momento sin temor a que existan diferencias entre los valores enviados y los valores reales en el formulario.
<script> let email = ""; let password = ""; let isLoading = false; const handleSubmit = () => { isLoading = true; // Simulate network request setTimeout(() => { isLoading = false; // Authorize the user }, 1000); }; </script> <style> /* Style is unchanged */ </style> <form on:submit|preventDefault={handleSubmit}> <h1></h1> <label>Email</label> <input name="email" placeholder="[email protected]" bind:value={email} /> <label>Password</label> <input name="password" type="password" bind:value={password} /> {#if isLoading}Logging in...{:else}Log in {/if} </form>
Las variables de estado se parecen a las variables comunes de JavaScript, pero para sincronizarlas con los valores del formulario (vincularlas a los campos del formulario), es necesario usar la directiva bind:value
. También hay un par de cosas desconocidas:
on:submit|preventDefault
es una forma abreviada de prevenir el comportamiento predeterminado de los eventos. Es más cómodo de esta manera que tener que escribire.preventDefault()
cada vez.{#if isLoading}Logging in...{:else}Log in {/if}
es una parte de la sintaxis de la plantilla de Svelte. Como no hay JS en el bloque de plantilla, hay una sintaxis especial para usar ifs, bucles, etc.
Finalmente, usemos las opciones disponibles usando el estado para agregar validación a nuestro formulario. Se puede lograr creando otra variable de estado errors
, que se llenará de errores cuando el formulario se envíe con valores no válidos.
<script> let email = ""; let password = ""; let isLoading = false; let errors = {}; const handleSubmit = () => { errors = {}; if (email.length === 0) { errors.email = "Field should not be empty"; } if (password.length === 0) { errors.password = "Field should not be empty"; } if (Object.keys(errors).length === 0) { isLoading = true; // Simulate network request setTimeout(() => { isLoading = false; // Authorize the user }, 1000); } }; </script> <style> // Previous styles unchanged .errors { list-style-type: none; padding: 10px; margin: 0; border: 2px solid #be6283; color: #be6283; background: rgba(190, 98, 131, 0.3); } </style> <form on:submit|preventDefault={handleSubmit}> <h1></h1> <label>Email</label> <input name="email" placeholder="[email protected]" bind:value={email} /> <label>Password</label> <input name="password" type="password" bind:value={password} /> <button type="submit"> {#if isLoading}Logging in...{:else}Log in {/if} </button> {#if Object.keys(errors).length > 0} <ul class="errors"> {#each Object.keys(errors) as field} <li>{field}: {errors[field]}</li> {/each} </ul> {/if} </form>

El formulario está casi completo. Lo único que queda es un mensaje de éxito tras la autenticación exitosa.

Vamos a crear una variable de estado para realizar un seguimiento de los envíos exitosos que es false
de forma predeterminada. Después de enviar correctamente un formulario, el valor de esta variable debe establecerse en true
.
let isSuccess = false;
La función que maneja el envío del formulario también debe cambiarse para seguir la lógica de alternar isSuccess
después de una operación exitosa.
const handleSubmit = () => { errors = {}; if (email.length === 0) { errors.email = "Field should not be empty"; } if (password.length === 0) { errors.password = "Field should not be empty"; } if (Object.keys(errors).length === 0) { isLoading = true; // Simulate network request setTimeout(() => { isLoading = false; isSuccess = true; // Authorize the user }, 1000); } };
Esta modificación hace que el formulario entre en estado de éxito tan pronto como se complete el envío.
Pero si revisa su servidor de desarrollo, no encontrará ningún cambio en el comportamiento del formulario. Cambiamos el código pero aún no hemos tocado la plantilla. Necesitamos agregar instrucciones a la plantilla para mostrar un mensaje de éxito cuando un usuario haya iniciado sesión correctamente. La sintaxis de la plantilla de Svelte nos permite implementar eso fácilmente:
<form on:submit|preventDefault={handleSubmit}> {#if isSuccess} <div class="success"> <br /> You've been successfully logged in. </div> {:else} <h1></h1> <label>Email</label> <input name="email" placeholder="[email protected]" bind:value={email} /> <label>Password</label> <input name="password" type="password" bind:value={password} /> <button type="submit"> {#if isLoading}Logging in...{:else}Log in {/if} </button> {#if Object.keys(errors).length > 0} <ul class="errors"> {#each Object.keys(errors) as field} <li>{field}: {errors[field]}</li> {/each} </ul> {/if} {/if} </form>
Resumen con propiedades
Hemos resuelto todo sobre el estado del componente interno. Ahora es el momento de revisar las dependencias externas llamadas propiedades o "accesorios". Los apoyos son entradas o argumentos pasados al componente para describirle lo que debería aparecer o cómo debería comportarse el componente.
La declaración de una propiedad se parece al estado, excepto por la palabra clave export
.
<script> export let answer; </script> <p>The answer is {answer}</p>
<script> import Nested from './Nested.svelte'; </script> <Nested answer={42}/>
Se trata de las propiedades. Declarar y aprobar: todo lo que necesita saber para usar accesorios.
Pero, ¿cómo se aplican estas propiedades al componente del formulario de inicio de sesión? Los accesorios pueden hacer que nuestro formulario de inicio de sesión sea más genérico al extraer la función de envío en una propiedad. Le permitirá usar este componente con cualquier acción de envío que necesite (solicitud a un servidor de prueba, solicitud a un servidor real, etc.). Esta prop se llamará submit
y será una función que devuelve una promesa resuelta si la acción de envío ha tenido éxito y una promesa rechazada si hay un error. Declaremos el accesorio con el ejemplo anterior:
export let submit;
El controlador de envío dentro del formulario de inicio de sesión también debe editarse para usar la nueva propiedad de submit
.
const handleSubmit = () => { errors = {}; if (email.length === 0) { errors.email = "Field should not be empty"; } if (password.length === 0) { errors.password = "Field should not be empty"; } if (Object.keys(errors).length === 0) { isLoading = true; submit({ email, password }) .then(() => { isSuccess = true; isLoading = false; }) .catch(err => { errors.server = err; isLoading = false; }); } };
El componente parece estar listo. Sin embargo, si regresa al formulario e intenta enviarlo, notará que el estado del botón no ha cambiado desde que se cargó. Además, hay una excepción en la consola: Uncaught TypeError: submit is not a function
. Por supuesto, declaramos el accesorio pero olvidamos pasarlo. Declaremos una función en el componente de la aplicación y pasémosla al formulario de inicio de sesión.
const submit = ({ email, password }) => new Promise((resolve, reject) => setTimeout(resolve, 1000));
<section> <LoginForm submit={submit} /> </section>
Ahora el formulario funciona según lo previsto. Puede mostrar errores e informar al usuario si el inicio de sesión se ha realizado correctamente.

Uso compartido de contexto
Parece que todo lo necesario para construir una aplicación está en la lista. Con las propiedades y el estado interno, estamos listos para comenzar. Sin embargo, eso es solo parcialmente cierto. Estos dos puntos generales permiten diseñar ZEPA de alta complejidad. Sin embargo, si intenta compartir datos entre muchos componentes diferentes, le resultará muy difícil.
El ejemplo más simple es tener una variable user
accesible globalmente. Muchos componentes deberían cambiar su comportamiento en relación con el usuario, según el rol, la edad, el estado, etc. del usuario. Sin embargo, no es SECO repetirnos al pasar al usuario a cada componente de la aplicación usando accesorios.
Svelte tiene una solución para esto: la API de contexto.
La API de contexto proporciona un mecanismo para que los componentes "hablen" entre sí sin pasar datos y funciones como accesorios o enviar muchos eventos. Es una característica avanzada pero útil.
Agreguemos el contexto del usuario al formulario de inicio de sesión que estamos diseñando. Cree un archivo userContext.js
dentro de la carpeta src
con el siguiente contenido:
export const key = "userContext"; export const initialValue = null;
key
es un identificador único para el contexto, ya que una aplicación puede tener un número ilimitado de contextos diferentes que deben permanecer accesibles. initialValue
es solo un valor predeterminado para el contexto antes de que se establezca.
El siguiente paso es agregar el contexto a nuestra aplicación. Navegue hasta el archivo App.svelte
y agregue 2 declaraciones de importación:
import { onMount, setContext } from "svelte"; import { key as userContextKey, initialValue as userContextInitialValue } from "./userContext";
Mirando el código anterior, puede preguntarse qué estamos importando del paquete svelte
. onMount
es una función auxiliar que requiere una función de devolución de llamada como argumento. Esta devolución de llamada se ejecutará cuando el componente actual se esté montando (al comienzo de la carga del componente). setContext
es una función setter para un contexto. Requiere la clave del contexto y un nuevo valor como argumentos.
Usemos la función onMount
para establecer el valor predeterminado para el contexto:
onMount(() => { setContext(userContextKey, userContextInitialValue); });
Y modifique la función de submit
para establecer el contexto del usuario:
const submit = ({ email, password }) => new Promise((resolve, reject) => { setTimeout(() => { setContext(userContextKey, { name: "Foo", lastName: "Bar", email: "[email protected]" }); resolve(); }, 1000); });
Eso es todo. Un envío exitoso cambiará el contexto del usuario a un objeto de usuario falso al que se puede acceder mediante un captador de contexto getContext
:
<script> import { getContext } from 'svelte'; import { key as userContextKey } from "./userContext"; const user = getContext(key); </script>
Resumen
Svelte es una poderosa herramienta capaz de alto rendimiento y con una API flexible. Además de los conceptos básicos cubiertos en esta publicación, Svelte tiene las siguientes características listas para usar:
- Declaraciones y sentencias reactivas
- Esperar bloques de plantilla
- Enlace de dimensión
- Una tienda global como Redux
- Ayudantes de animación y transición
- Un ayudante de depuración
En resumen, Svelte es una gran biblioteca que satisface todas las necesidades para construir SPA y más. Puede competir con los jugadores más importantes del mercado e incluso ganar. Sin embargo, lo que podría usar en este momento es el soporte en la comunidad de desarrolladores front-end.
Nota: Todo el código de este artículo se puede encontrar en el repositorio de GitHub teimurjan/svelte-login-form
. La demostración del formulario de inicio de sesión está disponible aquí.