9 points par GN⁺ 2025-02-19 | 7 commentaires | Partager sur WhatsApp
  • Récapitulatif des problèmes rencontrés après la mise à niveau récente d’une application web vers Svelte 5
    • La réactivité profonde et le cycle de vie modifié ont entraîné des comportements inattendus
  • J’ai longtemps apprécié Svelte 3/4, mais je ne pense pas choisir Svelte pour de nouveaux projets à l’avenir

La nécessité de la vitesse

  • L’équipe Svelte a tenté d’optimiser les performances via la deep reactivity, et a obtenu de meilleures performances
  • Auparavant déjà, Svelte offrait de bonnes performances grâce au processus de compilation, ce qui constituait une force distincte par rapport aux autres frameworks
  • Cela rendait le framework opaque et le débogage difficile, mais cela semblait être un compromis acceptable du point de vue des performances et de la productivité

La nécessité de la vitesse

  • Le principal changement mis en avant par l’équipe Svelte dans Svelte 5 est la « deep reactivity », destinée à améliorer les performances grâce à une réactivité plus fine
  • Dans les versions précédentes de Svelte, cet objectif était surtout atteint via le compilateur Svelte
    • Le fait de pouvoir réorganiser la logique interne sans obliger les développeurs à apprendre de nouveaux concepts mettait en valeur l’originalité de Svelte
  • En même temps, ce processus de compilation rendait le framework opaque, ce qui compliquait le débogage des problèmes complexes
    • Des erreurs difficiles à attribuer à leur cause apparaissaient à cause de bugs du compilateur lui-même, et il fallait parfois refactoriser entièrement le composant fautif pour les résoudre
  • Malgré cela, cela restait à mes yeux un compromis raisonnable entre vitesse et productivité, au point d’accepter l’inconvénient de devoir réinitialiser périodiquement les projets

Svelte n’est pas du Javascript

  • Svelte 5 double ce compromis
  • La différence essentielle est que le point d’équilibre entre abstraction et performance a dépassé l’étape de compilation pour pénétrer aussi la partie runtime
    • Utilisation de proxies pour prendre en charge la deep reactivity
    • État implicite du cycle de vie des composants
  • Ces deux changements améliorent les performances et donnent à l’API développeur une apparence plus fluide
  • Qu’y a-t-il à ne pas aimer ? Malheureusement, ces deux fonctionnalités sont des exemples typiques de leaky abstraction
    • Au final, elles créent un environnement plus complexe à gérer pour les développeurs

Les proxies ne sont pas des objets

  • Grâce aux proxies, l’équipe Svelte a pu encore améliorer un peu les performances du framework sans demander de travail supplémentaire aux développeurs
    • Dans des frameworks comme React, faire passer l’état à travers plusieurs composants peut facilement provoquer des rerenders inutiles ; Svelte a introduit les proxies pour réduire cela
    • Le compilateur Svelte évitait déjà certains problèmes liés à la comparaison du virtual DOM, mais l’équipe semble avoir jugé que les proxies pouvaient encore améliorer les performances
    • L’équipe Svelte a également indiqué que les proxies amélioraient l’expérience développeur, avançant l’idée qu’ils permettent de « maximiser à la fois l’efficacité et la facilité d’utilisation »
  • Le problème, c’est que Svelte 5 paraît plus simple en apparence, alors qu’il ajoute en réalité davantage d’abstractions
    • Par exemple, utiliser un proxy pour détecter les méthodes de tableau évite d’avoir à écrire du code comme value = value dans Svelte 4
    • Dans Svelte 4, les développeurs devaient comprendre jusqu’à un certain point le fonctionnement du compilateur pour déclencher la réactivité. Svelte 5 donne au contraire l’impression qu’on peut « oublier le compilateur », mais ce n’est pas vraiment le cas
    • À mesure que l’on gagne en confort grâce à cette nouvelle abstraction, le nombre de règles que les développeurs doivent connaître pour faire fonctionner le compilateur comme prévu augmente aussi
  • Après avoir longtemps utilisé Svelte, j’en suis progressivement venu à utiliser davantage les stores Svelte et moins les déclarations réactives
    • Les stores Svelte restent fondamentalement plus proches des concepts Javascript, la méthode update est simple à appeler, et la syntaxe $ n’était qu’un avantage supplémentaire
    • Les proxies, comme les déclarations réactives, posent le problème de « sembler être une chose alors qu’ils se comportent différemment au niveau des frontières »
  • Lors de ma première utilisation de Svelte 5, tout semblait fonctionner, mais quand j’ai voulu enregistrer un état proxy dans IndexedDB, j’ai obtenu une DataCloneError
    • Pire encore, pour savoir avec certitude si une valeur est un proxy, il faut essayer une structured clone dans un try/catch, ce qui a un coût en performances
    • Au final, il faut se souvenir de ce qui est un proxy et utiliser systématiquement $state.snapshot dans les contextes externes qui ne reconnaissent pas les proxies
    • On se retrouve ainsi dans une situation où, contrairement à l’intention initiale selon laquelle « l’abstraction améliore le confort du développeur », elle impose en pratique davantage de règles et de procédures complexes

Un composant n’est pas une fonction

  • Si le virtual DOM a gagné en popularité vers 2013, c’est parce qu’il permettait de modéliser les applications comme une composition de fonctions
    • Svelte a conservé une approche fondée sur le compilateur plutôt que sur le virtual DOM, pour simplifier les fonctions de cycle de vie et améliorer les performances
    • Mais avec Svelte 5, la notion de cycle de vie a été réintroduite d’une manière proche des React Hooks
  • Dans React, les Hooks sont une abstraction destinée à réduire le code lié à l’état dans les méthodes de cycle de vie
    • Le code devient plus propre, mais il y a beaucoup de points auxquels le développeur doit faire attention, par exemple lorsqu’un setTimeout référence un état
    • Dans Svelte 4 aussi, du code asynchrone pouvait poser problème s’il accédait à un élément du DOM au moment où le composant était démonté
    • Désormais, dans Svelte 5, il semble qu’un état implicite ait été ajouté au cycle de vie des composants pour orchestrer les changements d’état et les effets
  • La documentation officielle de $effect l’explique ainsi :
    > « $effect peut être placé n’importe où, mais il doit être appelé pendant l’initialisation du composant (ou pendant qu’un effet parent est actif) et disparaît lorsque le composant (ou l’effet parent) est démonté »
  • Cela suggère que, contrairement à l’explication selon laquelle le cycle de vie ne comporte que deux phases — montage et démontage —, il existe en réalité une structure d’effets plus complexe qui nécessite de suivre les changements d’état
  • La documentation officielle sur le cycle de vie affirme qu’il n’y a pas de « before update/after update », mais introduit de nouveaux concepts comme $effect.pre et tick
  • Cela signifie en pratique qu’il faut comprendre non seulement le montage et le démontage, mais aussi le moment où les changements d’état se produisent
  • Le point qui m’a réellement posé problème à l’usage est que même l’état transmis à une fonction sans rapport avec Svelte reste lié au cycle de vie du composant
  • Par exemple, j’utilisais un pattern où une fenêtre modale était gérée par un store, avec un callback transmis à un composant enfant
    const { value } = $props()  
    const callback = () => console.log(value)  
    const openModal = () => pushModal(MyModal, { callback })  
    
  • Si ce code se trouve à l’intérieur du composant modal, le composant qui a appelé la modale est démonté en premier, et à ce moment-là value devient undefined
  • Un exemple minimal de reproduction a été publié dans ce dépôt
  • Autrement dit, les props référencées par un callback encore vivant après la fin du cycle de vie du composant deviennent soudainement undefined
  • Ce comportement diffère du Javascript de base, et donne l’impression que Svelte effectue lui-même une sorte de garbage collection
  • Il y a sans doute des raisons d’ingénierie derrière cela, mais le comportement reste surprenant

Conclusion

  • Ce qui est facile a clairement de l’attrait, mais comme l’a dit Rich Hickey, facile ne veut pas dire simple
  • Comme Joel Spolsky, je n’apprécie pas particulièrement que des comportements inattendus se produisent
  • Svelte a jusqu’ici montré beaucoup de « magie », mais dans cette version, il y a désormais trop de choses à mémoriser pour utiliser cette magie, et le coût dépasse le bénéfice
  • Le but de ce texte n’est pas de critiquer l’équipe Svelte, et je suis bien conscient que beaucoup de personnes préfèrent Svelte 5 (et les React Hooks)
  • L’important est l’équilibre entre offrir de la commodité aux utilisateurs et leur laisser le contrôle
  • Un bon logiciel digne de ce nom repose non sur l’« intelligence », mais sur la compréhension
  • À mesure que les outils d’IA progressent, il devient important de choisir non pas des outils qui font perdre de vue ce que l’on fait, mais des outils qui exploitent la sagesse déjà accumulée et aident à approfondir la compréhension
  • Merci à Rich Harris et à l’équipe pour toutes ces années d’expérience de développement agréable. J’espère que ce texte constituera un retour qui, sans être parfait, ne sera pas pour autant inexact

7 commentaires

 
firea32 2025-02-24

Les proxies rendent la vie plus facile à ceux qui les créent, mais ils énervent ceux qui doivent les déboguer, haha.

 
bichi 2025-02-21

Pour les side projects, SolidJS est numéro un pour la DX >o< / quel bonheur

 
pcj9024 2025-02-20

Je pense que c’est grâce à des alternatives comme Svelte que React/Next.js ont aussi pu être fortement stimulés.
Fondamentalement, Svelte est un language, donc j’espère qu’il saura aussi bien montrer la direction que doit prendre un langage de description d’UI.

Pour ma part, j’utiliserai React.

 
iolothebard 2025-02-20

Le trop est l’ennemi du bien
S’égarer par excès d’ardeur
Une surcouche sur une surcouche

 
colus001 2025-02-20

Je pense qu’il a changé de façon étrange en subissant une influence non négligeable de React, et surtout de Next. +page est difficile à comprendre si on le regarde sans connaître Svelte, et les runes comme $state ou $derived donnent l’impression de suivre React ; à choisir, l’époque où l’on mettait simplement $: devant une variable me paraît meilleure. Une syntaxe vieillotte comme {#each a in array} {/each} reste supportable, mais elle reste toujours fastidieuse. S’il s’agit d’un gain de performances grâce à une réactivité optionnelle, je pense que SolidJS va dans une bien meilleure direction. Comme il utilise JSX tel quel, il est aussi relativement plus facile d’y migrer depuis React. Il est même étonnant que SolidJS reçoive relativement si peu d’attention.

 
xiniha 2025-02-19

J’ai l’impression que les Signals se dirigent vers le Trough of disillusionment du Gartner hype cycle 🤔 À mesure que les cas d’usage se précisent, je me dis que leur évaluation pourrait progressivement s’améliorer.

 
GN⁺ 2025-02-19
Avis Hacker News
  • Au début, les runes ne m’intéressaient pas vraiment. Mais j’ai changé d’avis quand j’ai vu qu’on peut importer des composants externes réactifs dans des templates .svelte et encapsuler la réactivité en interne. Cela signifie qu’on peut profiter des avantages de la réactivité tout en écrivant des tests vitest. C’est vraiment puissant et, AFAIK, unique dans le monde du frontend

    • La plupart des développeurs frontend ne testent pas du tout. Typescript est l’outil que les gens utilisent pour garantir la justesse, et il y a de bonnes raisons à cela. Mais les utilisateurs de Svelte ont toujours eu une vision étroite de typescript, et il y a aussi de bonnes raisons à cela
    • Personnellement, je préfère écrire du code frontend testable, et Svelte 5 est révolutionnaire sur ce point. C’est réactif dans le navigateur tout en étant aussi bon que des tests unitaires
    • Cela dit, le billet de blog dit vrai. L’ajout de proxies est vraiment très désagréable. React et Vue m’ont perdu quand ils ont commencé à empiler des abstractions sur des abstractions, et les proxies ont marqué ce point de départ
    • Le fait que Svelte 5 ne soit pas du JavaScript est <i>la raison pour laquelle j’aime Svelte 5</i>
    • Je pense qu’il existe deux grandes façons raisonnables de faire du frontend/web
        1. HTML statique ou templates rendus côté serveur, probablement avec HTMX
        1. Un langage/une plateforme qui compile vers JavaScript. Au minimum TypeScript, mais comme je pense que HTML et CSS sont en fait plutôt bons, JSX, React, Tailwind, etc. sont <i>exclus</i>, et Svelte 5 ainsi que quelques autres frameworks sont réellement une amélioration par rapport à du TypeScript vanilla
    • Svelte 5 est le gagnant évident de la catégorie 2
    • Il offre de beaux templates HTML, une propagation d’état simple et sensée, et permet d’écrire facilement du code modulaire. Il fonctionne bien avec CSS, permet souvent de créer de petites applis et outils jetables en un ou deux fichiers, tout en rendant possibles des applications plus grandes et sérieuses. C’est moins magique et moins surprenant que Svelte 4, et honnêtement, c’est agréable à utiliser. Heureusement, je me fiche d’IndexedDB
    • Aujourd’hui, je ne vois absolument aucune raison d’écrire une seule ligne de JavaScript, mais chacun fait comme il veut
  • Je développe activement une application SvelteKit déployée commercialement, et je voulais partager quelques réflexions sur l’expérience

    • Ce qui m’a d’abord attiré vers SvelteKit, c’était sa simplicité. Après avoir configuré le projet, je pouvais travailler sur un seul fichier HTML/JS/CSS à la fois, tout en profitant des avantages d’un framework moderne sans sa complexité. Cela me rappelait les débuts du développement web, quand il suffisait de déposer des fichiers HTML sur un serveur Apache pour que tout fonctionne
    • Mais voir Svelte s’éloigner de ce paradigme simple est décevant. Dès le départ, Rich Harris mettait en avant la facilité d’utilisation et la simplicité de Svelte comme arguments de vente majeurs. La version actuelle de SvelteKit n’est pas mauvaise, mais je préférais les versions précédentes. À l’époque, il n’y avait pas besoin de gérer une structure de routage comme +page. On pouvait placer les fichiers Svelte où on voulait, et ils se rendaient naturellement tout en offrant les avantages d’un framework moderne
    • Ces changements ajoutent une complexité qui n’était pas nécessaire auparavant et risquent d’éloigner Svelte de ce qui faisait son attrait à l’origine. J’ai choisi en fonction de ce que je connaissais déjà
  • C’est dommage qu’EmberJS ait disparu. Son API est restée assez stable au cours des dix dernières années. Ironiquement, quelqu’un qui a écrit des applis EmberJS pendant ces dix dernières années aura probablement moins souffert des migrations que quelqu’un qui a fait la même chose avec React, Svelte, Vue, etc.

    • Malheureusement, l’équipe Ember a pris quelques décisions étranges au début, et ce n’était pas facile à comprendre par rapport au JavaScript standard (même si, pour la plupart, cela a été corrigé depuis)
    • Que ce soit du JavaScript ou non est bien moins important que la stabilité de l’API
    • Personnellement, le problème de JavaScript, c’est qu’il change trop souvent
  • Les deux liens Github listés par l’auteur en haut du billet pointent vers le même problème, et ce problème a une solution (use $state.raw)

    • Je suis fan de Svelte depuis Svelte 2 ou 3. C’était ce qui se rapprochait le plus de l’écriture de HTML/CSS/JS vanilla tout en offrant les avantages d’un framework (et avec Sass et TypeScript en plus). C’était fantastique
    • Svelte 5 me mettait mal à l’aise au début à cause de l’étrangeté des runes. Après avoir mis à niveau un projet et travaillé sur d’autres projets, ce n’est finalement pas si mal. Svelte 5 n’autorise pas de mélanger l’ancienne et la nouvelle manière de gérer l’état, et les messages d’erreur sont généralement informatifs
    • Je vois dans ces commentaires des gens dire que htmx et le JS vanilla sont objectivement meilleurs... non ? Peut-être pour ce que vous faites. Personnellement, je trouve toujours Svelte bien plus facile à comprendre que React. Pour ceux qui se soucient des benchmarks, Svelte est aussi rapide que SolidJS (les utilisateurs de React pourraient sans doute passer facilement à Solid, la syntaxe semble proche)
  • Svelte 5 n’est pas du JavaScript de la <i>pire</i> des façons. Il ne résout pas les problèmes de js et propose des abstractions fuyantes pour certains problèmes du frontend. Je pense que Solid va dans une meilleure direction que Svelte, parce que Solid ne dépend pas d’un nouveau langage. Mais comme js n’est pas idéal, il y a un instinct naturel à vouloir créer autre chose que du js. Elm est le prédécesseur de svelte. Mais je pense qu’on peut faire mieux...[0]

  • J’ai commencé à utiliser Svelte 5 parce que je détestais vraiment les stores dans Svelte 4. J’utilise Sveltekit et Svelte 5 sur un nouveau projet, et je dois dire que... la productivité avec React reste imbattable, même si la stack Sveltekit/Svelte est techniquement meilleure

    • Quelques points vraiment agaçants : toutes les pages portent des noms comme +page.server.ts ou +page.svelte, ou leurs variantes, ce qui rend le code difficile à rechercher facilement. Les outils de Svelte existent séparément de tsc et d’ESLint, ce qui les rend plus difficiles à intégrer à la CI et à utiliser en développement
    • Il y a aussi d’étranges problèmes de compatibilité avec les versions précédentes. Par exemple, la plupart des packages Svelte utilisent encore des stores, donc il faut se battre avec deux mondes de versions, et écrire du code devient parfois vraiment confus. En plus, le HMR de Svelte semble encore immature, donc l’état risque d’être cassé quand un module Svelte est rechargé
    • J’ai vraiment envie d’aimer Svelte. Le rendu est assez rapide et j’aime les idées derrière. Mais la productivité de React reste imbattable
  • Dire que Svelte n’est pas du JavaScript à cause d’un comportement inattendu quand on passe une closure dans un callback me paraît étrange. Un meilleur titre serait : « Svelte 5 me surprend et je n’aime pas ça »

  • Si vous cherchez une bibliothèque qui permet de créer des composants et des applis en pur JavaScript, jetez un œil à Lit : Lit

    • Il existe un package supplémentaire pour les signaux afin d’obtenir une réactivité profonde, avec pour objectif une intégration avec la future proposition Signals de la TC39 : Signals
    • Lit est utilisé dans de grandes applications comme Photoshop, Reddit, Home Assistant et The Internet Archive
  • Vous voulez une expérience frontend raisonnable ? Utilisez JavaScript vanilla, les web components, htmx et Blazor

    • Les frameworks JS sont de la folie, pour une raison ou une autre