9 puntos por GN⁺ 2025-02-19 | 7 comentarios | Compartir por WhatsApp
  • Resumen de los problemas encontrados tras actualizar recientemente una aplicación web a Svelte 5
    • Se produjeron comportamientos inesperados por la funcionalidad de reactividad profunda y los cambios en el ciclo de vida
  • Aunque disfruté mucho Svelte 3/4 durante bastante tiempo, no creo que vuelva a elegir Svelte para proyectos nuevos

La necesidad de la velocidad

  • El equipo de Svelte intentó optimizar el rendimiento mediante deep reactivity, logrando un mejor desempeño
  • Ya antes ofrecía un rendimiento rápido gracias al proceso de compilación, y eso era una fortaleza que lo diferenciaba de otros frameworks
  • Aunque eso hacía al framework más opaco y difícil de depurar, me parecía un trade-off aceptable en términos de rendimiento y productividad

La necesidad de la velocidad

  • El principal cambio en el que se enfoca el equipo de Svelte en Svelte 5 es la “deep reactivity”, con la que busca mejorar el rendimiento mediante una reactividad más fina
  • En versiones anteriores de Svelte, este objetivo se lograba principalmente aprovechando el compilador de Svelte
    • Que el desarrollador no tuviera que aprender conceptos nuevos y que fuera fácil reorganizar la lógica interna resaltaba la originalidad de Svelte
  • Al mismo tiempo, este proceso de compilación volvía opaco al framework, lo que dificultaba depurar problemas complejos
    • Debido a bugs del propio compilador, podían aparecer errores cuya causa era difícil de identificar, y a veces solo se resolvían refactorizando por completo el componente problemático
  • Aun así, me parecía un compromiso razonable por la velocidad y la productividad, así que incluso toleré la incomodidad de tener que reiniciar periódicamente los proyectos

Svelte no es JavaScript

  • Svelte 5 duplica este trade-off
  • La diferencia clave es que el punto de equilibrio entre abstracción y rendimiento ya no se queda en la etapa de compilación, sino que se mete también en el runtime
    • Uso de proxies para soportar deep reactivity
    • Estado implícito del ciclo de vida del componente
  • Estos dos cambios mejoran el rendimiento y hacen que la API para desarrolladores se vea más pulida
  • ¿Qué podría tener de malo? Lamentablemente, estas dos funciones son un ejemplo clásico de leaky abstraction
    • Al final provocan un entorno más complejo de manejar para el desarrollador

Los Proxies no son objetos

  • Gracias al uso de Proxy, el equipo de Svelte pudo exprimir un poco más el rendimiento del framework sin exigir trabajo adicional al desarrollador
    • En frameworks como React, al pasar estado a través de varios componentes es fácil provocar rerenderizados innecesarios, y Svelte introdujo Proxy con el objetivo de reducir eso
    • El compilador de Svelte ya evitaba algunos problemas que pueden surgir del diffing del DOM virtual, pero parece que consideraron que con Proxy podían mejorar aún más el rendimiento
    • El equipo de Svelte también mencionó que Proxy ayuda a mejorar la experiencia del desarrollador, sosteniendo que “puede maximizar tanto la eficiencia como la facilidad de uso”
  • El problema es que Svelte 5 parece más simple por fuera, pero en realidad añade más abstracción
    • Por ejemplo, usar Proxy para detectar métodos de arreglos trae la ventaja de no tener que escribir código como value = value, como sí ocurría en Svelte 4
    • En Svelte 4, para activar la reactividad el desarrollador tenía que entender en cierta medida cómo funcionaba el compilador. En cambio, Svelte 5 da la impresión de que “ya puedes olvidarte del compilador”, pero en realidad no es así
    • Tanto como gana en comodidad gracias a la nueva abstracción, también aumentan las reglas que el desarrollador debe conocer para hacer que el compilador se comporte como se espera
  • Después de usar Svelte durante mucho tiempo, personalmente fui usando cada vez más Svelte store y menos declaraciones reactivas
    • Las Svelte store son, en esencia, más cercanas a conceptos básicos de JavaScript; llamar al método update es simple, y la sintaxis con $ era más bien una ventaja adicional
    • Igual que las declaraciones reactivas, Proxy provoca el problema de que “parece una cosa, pero en los puntos límite se comporta de otra manera”
  • Cuando empecé a usar Svelte 5, todo parecía funcionar bien, pero al intentar guardar estado Proxy en IndexedDB apareció un DataCloneError
    • Peor aún: para saber con certeza si un valor es Proxy, hay que intentar una clonación estructurada con try/catch, lo que tiene un costo de rendimiento
    • Al final, uno termina teniendo que recordar qué es Proxy y usar $state.snapshot cada vez en contextos externos que no reconocen Proxy
    • Eso termina creando una situación en la que, en contra de la intención original de que “la abstracción mejora la comodidad del desarrollador”, se le exigen al desarrollador reglas y procedimientos más complejos

Los componentes no son funciones

  • La razón por la que el DOM virtual se volvió popular hacia 2013 fue que permitía modelar las aplicaciones como una composición de funciones
    • Svelte había mantenido un enfoque de usar un compilador en lugar del DOM virtual para simplificar las funciones del ciclo de vida y mejorar el rendimiento
    • Sin embargo, en Svelte 5 el concepto de ciclo de vida volvió a introducirse de una forma parecida a React Hooks
  • En React, Hooks es una abstracción que reduce el código relacionado con estado dentro de los métodos del ciclo de vida
    • El código queda más limpio, pero hay muchas cosas a las que el desarrollador debe prestar atención, como cuando se consulta estado dentro de setTimeout
    • Incluso en Svelte 4 podía haber problemas si código asíncrono accedía a elementos del DOM en el momento en que el componente se desmontaba
    • Ahora, en Svelte 5, parece que se añadió estado implícito al ciclo de vida del componente para coordinar cambios de estado y efectos
  • La documentación oficial sobre $effect lo explica así:

    “$effect can be placed anywhere, but can only be called during component initialisation (or while a parent effect is active). It will only run while the component (or parent effect) is mounted.”

  • Esto sugiere que, a diferencia de la explicación de que el ciclo de vida solo tiene dos etapas, mount/unmount, en realidad existe una estructura compleja de efectos que requiere rastrear cambios de estado
  • La documentación oficial del ciclo de vida dice que “no hay before update/after update”, pero aparecen conceptos nuevos como $effect.pre y tick
  • En la práctica, eso significa que además de mount/unmount también hace falta entender los momentos en que cambia el estado
  • La parte que realmente causó problemas en uso real fue que incluso el estado pasado a funciones ajenas a Svelte queda atado al ciclo de vida del componente
  • Por ejemplo, se usaba un patrón en el que una ventana modal se gestionaba con una store y se pasaba un callback al componente hijo
    const { value } = $props()  
    const callback = () => console.log(value)  
    const openModal = () => pushModal(MyModal, { callback })  
    
  • Si este código está dentro del componente que invoca el modal, el componente que llamó al modal se desmonta primero, y en ese momento value pasa a ser undefined
  • En ese repositorio hay un ejemplo mínimo reproducible
  • Es decir, props a las que hacía referencia un callback que seguía vivo incluso después de terminado el ciclo de vida del componente pasan repentinamente a ser undefined
  • Esto se comporta distinto al JavaScript básico, y da la impresión de que Svelte está haciendo algo parecido a recolección de basura por su cuenta
  • Puede haber una razón de ingeniería detrás, pero como comportamiento inesperado resulta sorprendente

Conclusión

  • Lo fácil sin duda resulta atractivo, pero como dijo Rich Hickey, fácil no significa simple
  • Como decía Joel Spolsky, no me agrada cuando ocurren comportamientos inesperados
  • Svelte ha mostrado mucha “magia” hasta ahora, pero en esta versión hay demasiado que memorizar para poder usar esa magia, y la carga termina siendo mayor que el beneficio
  • El punto de este texto no es criticar al equipo de Svelte; al contrario, reconozco que hay muchas personas que prefieren Svelte 5 (y React Hooks)
  • Lo importante es el equilibrio entre ofrecer comodidad al usuario y permitir que el usuario conserve el control
  • El software realmente bueno no se basa en ser “ingenioso”, sino en la “comprensión”
  • A medida que las herramientas de IA avanzan, es importante elegir herramientas que aprovechen la sabiduría acumulada y ayuden a una comprensión profunda, en lugar de herramientas que hagan que uno no sepa lo que está haciendo
  • Gracias a Rich Harris y al equipo por la grata experiencia de desarrollo hasta ahora. Espero que este texto sirva como feedback que no sea del todo desacertado

7 comentarios

 
firea32 2025-02-24

Las proxy le facilitan la vida a quien las crea, pero hacen enojar a quien tiene que depurarlas jajaja

 
bichi 2025-02-21

Sideproject tiene el mejor DX de solidjs >.< / felicidad

 
pcj9024 2025-02-20

Creo que, como existían alternativas como Svelte, React/nextjs también pudo recibir un gran estímulo.
En esencia, Svelte es un language, así que espero que también pueda mostrar bien la dirección hacia la que debería avanzar un lenguaje para describir UI.

Yo usaré React

 
iolothebard 2025-02-20

Demasiado es tan malo como demasiado poco
obsesión que lleva al desvío
poner un techo sobre otro techo

 
colus001 2025-02-20

Creo que cambió de una forma extraña al recibir bastante influencia de React y, en especial, de Next. +page es difícil de entender si lo ves sin conocer Svelte, y los rune como $state y $derived parecen seguir a React; sinceramente, la época en la que solo se ponía $: delante de una variable me parecía mejor. También puedo tolerar una sintaxis anticuada como {#each a in array} {/each}, pero sigue siendo molesta. Si se trata de mejorar el rendimiento mediante reactividad opcional, me parece que SolidJS va en una dirección mucho mejor. Como usa JSX tal cual, en comparación también es más fácil pasarse desde React. Hasta resulta extraño que SolidJS reciba relativamente tan poca atención.

 
xiniha 2025-02-19

Parece que Signals se está acercando al Trough of disillusionment del Gartner hype cycle 🤔. A medida que sus casos de uso se vayan definiendo mejor, creo que su evaluación podría mejorar.

 
GN⁺ 2025-02-19
Opinión de Hacker News
  • Al principio no me interesaban mucho las runes. Pero cambié de opinión cuando vi que puedes importar componentes externos reactivos a una plantilla .svelte y encapsular la reactividad internamente. Eso significa que puedes escribir pruebas con vitest y aun así obtener los beneficios de la reactividad. Es realmente poderoso y, AFAIK, algo único en el mundo del frontend

    • La mayoría de los desarrolladores frontend no hacen pruebas en absoluto. TypeScript es la herramienta que la gente usa para garantizar corrección, y hay una buena razón para eso. Pero los usuarios de Svelte siempre han tenido una visión limitada de TypeScript, y también hay una buena razón para eso
    • Personalmente prefiero escribir código frontend que se pueda probar, y Svelte 5 es revolucionario en ese sentido. Es reactivo en el navegador, pero casi tan bueno como una prueba unitaria
    • Dicho todo esto, la publicación del blog dice la verdad. Agregar proxies se siente muy incómodo. React y Vue dejaron de convencerme cuando empezaron a apilar abstracciones sobre abstracciones, y los proxies fueron el punto de partida
    • Que Svelte 5 no sea JavaScript es <i>la razón por la que me gusta Svelte 5</i>
    • Creo que hay dos formas principales y razonables de hacer frontend/web
        1. HTML estático o plantillas renderizadas en servidor, quizá HTMX
        1. Un lenguaje/plataforma que compile a JavaScript. Como mínimo TypeScript, pero como creo que HTML y CSS en realidad son bastante buenos, JSX, React, Tailwind, etc. quedan <i>fuera</i>, y Svelte 5 junto con algunos otros frameworks en realidad mejoran sobre TypeScript vanilla
    • Svelte 5 es el claro ganador en la categoría 2
    • Tiene plantillas HTML excelentes, propagación de estado fácil y razonable, y facilita escribir código modular. Funciona bien con CSS, a menudo permite crear apps y herramientas simples de uno o dos archivos, y también puede usarse para aplicaciones más grandes y serias. Es menos mágico y sorprendente que Svelte 4 y, sinceramente, da gusto usarlo. Afortunadamente no me importa IndexedDB
    • Hoy en día no entiendo para nada por qué alguien escribiría una sola línea de JavaScript, pero cada quien a su manera
  • Estoy desarrollando activamente una aplicación SvelteKit desplegada comercialmente y quería compartir algunas ideas sobre la experiencia

    • Lo que inicialmente me atrajo de SvelteKit fue su simplicidad. Después de configurar el proyecto, podía trabajar en un solo archivo HTML/JS/CSS a la vez mientras aprovechaba los beneficios de un framework moderno sin complejidad. Me recordaba a los primeros tiempos del desarrollo web, cuando bastaba con soltar archivos HTML en un servidor Apache para que todo funcionara
    • Pero es decepcionante ver a Svelte alejarse de ese paradigma simple. Desde el principio, Rich Harris presentó la facilidad de uso y la simplicidad de Svelte como puntos clave de venta. La versión actual de SvelteKit no es mala, pero prefería la anterior. En ese entonces no había que lidiar con estructuras de enrutamiento como +page. Podías poner archivos Svelte donde quisieras y se renderizaban sin fricción, mientras seguías disfrutando de los beneficios de un framework moderno
    • Estos cambios añaden una complejidad que antes no era necesaria y podrían alejarse de lo que hizo atractivo a Svelte desde el inicio. Lo elegí con base en lo que ya conocía
  • Es una lástima que EmberJS haya desaparecido. Su API fue bastante estable durante los últimos 10 años. Irónicamente, alguien que haya escrito apps en EmberJS durante la última década probablemente tendrá menos dificultades de migración que alguien que haya hecho lo mismo con React, Svelte, Vue, etc.

    • Por desgracia, el equipo de Ember tomó algunas decisiones raras al principio y no era fácil de entender en comparación con JavaScript normal (aunque la mayoría ya se corrigieron)
    • Que sea o no JavaScript importa poco comparado con la estabilidad de la API
    • Personalmente, el problema de JavaScript es que cambia con demasiada frecuencia
  • Los dos enlaces de Github que el autor enumera al inicio de la publicación apuntan al mismo problema, y ese problema tiene solución (usa $state.raw)

    • Soy fan de Svelte desde la versión 2 o 3. Era lo más cercano a escribir HTML/CSS/JS vanilla mientras seguías obteniendo las ventajas de un framework (y usando Sass y TypeScript). Fantástico
    • Svelte 5 me daba mala espina porque las runes parecían raras. Después de actualizar proyectos y trabajar en otros, no está tan mal. Svelte 5 no permite mezclar la forma vieja y la nueva de manejar estado, y los mensajes de error en su mayoría son informativos
    • Veo gente en este hilo diciendo que htmx y JS vanilla son objetivamente mejores... ¿no? Tal vez para lo que tú haces. Personalmente, Svelte sigue siendo mucho más fácil de entender que React. Para quienes se preocupan por benchmarks, Svelte es tan rápido como SolidJS (los usuarios de React probablemente podrían cambiarse a Solid con facilidad, la sintaxis se siente parecida)
  • Svelte 5 no es JavaScript de la <i>peor</i> manera. No resuelve los problemas de js, y ofrece abstracciones con fugas para algunos problemas de frontend. Creo que Solid va en mejor dirección que Svelte. Solid no depende de un lenguaje nuevo. Sin embargo, existe ese impulso de crear algo que no sea js, porque js no es ideal. Elm es el precursor de svelte. Pero creo que se puede hacer algo mejor...[0]

  • Empecé a usar Svelte 5 porque realmente odiaba las stores en Svelte 4. Estoy usando Sveltekit y Svelte 5 en un proyecto nuevo y debo decirlo... la productividad de React sigue siendo imbatible, aunque Sveltekit y Svelte sean técnicamente mejores

    • Algunas cosas que me molestaron muchísimo: todas las páginas se llaman +page.server.ts o +page.svelte o alguna variante, así que es difícil buscar código fácilmente. Las herramientas de Svelte existen separadas de tsc y ESLint, por lo que es más difícil integrarlas en CI y usarlas en desarrollo
    • También hay problemas raros de compatibilidad con versiones anteriores. Por ejemplo, la mayoría de los paquetes de Svelte todavía usan stores, así que tienes que pelear con dos mundos de versiones y escribir código a veces se vuelve realmente confuso. Además, Svelte HMR todavía parece estar en una etapa temprana, así que cuando un módulo de Svelte se recarga puede arruinar el estado
    • De verdad quiero que Svelte me encante. Renderiza bastante rápido y me gustan las ideas detrás. Pero la productividad de React es imbatible
  • Se siente raro decir que Svelte no es JavaScript por un comportamiento inesperado al pasar un closure como callback. Un mejor título sería: "No me gusta Svelte 5 porque me sorprendió"

  • Si buscas una librería con la que puedas construir componentes y aplicaciones usando JavaScript puro, revisa Lit: Lit

    • Hay un paquete adicional de signals para reactividad profunda, y apunta a integrarse con la próxima propuesta Signals de TC39: Signals
    • Lit se usa en aplicaciones importantes como Photoshop, Reddit, Home Assistant y The Internet Archive
  • ¿Quieres una experiencia frontend razonable? Usa JavaScript vanilla, web components, htmx, Blazor

    • Los frameworks de JS son una locura, por la razón que sea