David Hockley

Premier pas avec Svelte

Bonjour à tous, aujourd'hui, nous allons parler de Svelte. De ce que c’est, de pourquoi c'est intéressant à appendre. Non, plus précisément : pourquoi c’est révolutionnaire. Parce que derrière Svelte, il y a un changement de paradigme.

La meilleure technique pour apprendre, c’est de faire. Quand je veux apprendre je regarde les exemples, et je bidouille.

Mais en faisant ça avec Svelte... c’était échec cuisant. Je ne comprenais pas comment marchait l'état, comment il se mettait à jour.

Alors, je me suis plongé dans la documentation. Elle précise que Svelte n'utilise pas de DOM virtuel, mais est un "framework UI qui compile les composants pour en faire du Javascript de base”. Contrairement à React, Vue ou Angular qui embarquent le framework dans la page. Qu'est-ce que ça veut dire, en pratique?

J'ai mis du temps à comprendre les principes du framework. Je cherchais un endroit où était identifié l’état de l’application. Mais, il n'y a pas d’equivalent de setState. Svelte se contente de :

<script>
let counter = 1;
</script>

Alors comment indiquer à Svelte ce qui relève de l’état ?

Mentalement, j’ai bloqué. Je n’ai pas compris ce qui se passait. Je me suis demandé comment c’était possible. La documentation avait annoncé la couleur, puisque la “tag line” de Svelte 2 était : “The magical disappearing UI framework“ Le framework d’interface qui disparaît, comme par magie.

En cherchant, je suis tombé sur une vidéo faite par Rich Harris, le créateur de Svelte. Et là, j'ai compris. Tout était effectivement dit dans la phrase : " Svelte compile les composants ".

En réalité, Svelte n'est PAS d’abord un framework. Pas en premier lieu. Avant tout, Svelte est un compilateur. Et… ce compilateur triche.

Ou plutôt il crée une illusion. Mais l’adjectif de “Magique” était bien choisi. Parce que comme un magicien, Svelte nous induit en erreur. Il donne l'impression qu'on code du Javascript, et ce n’est pas tout-à-fait vrai.

Quelle est la nature de cette illusion ?

Svelte triche en surchargeant l'opérateur =, en lui rajoutant un effet de bord. Il en fait une fonction, qui met à jour tous les endroits où la variable est utilisée. Il repère dans le HTML, au moment du build, là ou il y a des dépendances envers cette variable, et se branche dessus.

Et c'est là que l’absence de DOM virtuel prend tout son intérêt.

Pour mieux comprendre, comparons avec React. React garde en mémoire une copie l’arbre des composants - c’est ce qu’on appelle le “DOM Virtuel”. A chaque trame de rendu, React compare un à un les paramètres de chaque node de l’arbre des composants. Si un paramètre a changé, React rafraichit le rendu des nodes qui en dépendent.

Mais cette comparaison 1 à 1 sur tout l’arbre des composants est couteux.

Svelte, à l'inverse, suit directement les dépendances des valeurs, en surchargeant l'opérateur d'affectation = ainsi que toutes ses variations.

C’est justement le “égal” dans let counter=1qui définit l’état.

Svelte va plus loin encore, en surchargeant aussi la notion de label pour créer des dépendances. Voyons un exemple.

Le nom du label, le $, rappelle la notion d'Observable. On définit ici firstName a “world”, puis on définit greeting. Dans le label, on assigne “hello + firstName” à “greeting”. Pour finir on assigne la valeur“Bob” à firstName.

<script>
  let firstName = 'world';
  let greeting
  $: greeting = 'Hello ' + firstName; 
  firstName = 'Bob';
</script>
<h1> {greeting}!</h1>

Ici, Svelte affiche “Hello Bob!”

Mais le label, la ligne avec le dollar est avant l'affectation de "Bob" à firstName. Si on avait affaire à du JavaScript pur, exécuté dans l’ordre, greeting vaudrait “Hello world”.

Tout ce passe comme si avec le label, le dollar, le lien entre “greeting” et “firstName” est durable. Comme si on avait crée une dépendance.

Si on met un log, on y voit plus clair :

<script>
  let firstName = 'world';
  let greeting
  $: greeting = 'Hello ' + firstName; 
  firstName = 'Bob';
  console.log(greeting);
</script>

<h1> {greeting}!</h1>

Au moment du log, greeting vaut "undefined”. Le code dans le $ n'a donc pas encore été appelé. Explorons plus en détail.

La notation en label peut comporter un block. Mettons y donc également un log :

<script>
  let firstName = 'world';
  let greeting
  $: {
   greeting = 'Hello ' + firstName; 
   console.log(greeting);
  }
  firstName = 'Bob';
  console.log(greeting);
</script>

<h1> {greeting}!</h1>

A présent la console indique “undefined", puis "Hello Bob". Ca parait logique.

On peut définir plusieurs blocks avec des labels.

<script>
  let firstName = 'world';
  let greeting
  $: console.log(1, greeting);
  $: {
   greeting = 'Hello ' + firstName; 
   console.log(2, greeting);
  } 
  firstName = 'Bob';
  console.log(3, greeting);
</script>

<h1> {greeting}!</h1>

Ici, on pourrait s'attendre (merci React avec l'ordre des hooks) à ce que les blocks des labels soient exécutés dans l'ordre où ils sont déclarés.

Et bien… non, pas du tout. Dans la console on voit 3, puis 2 puis 1. Ici Svelte a détecté un graphe de dépendances.

Le block 2 dépend de “firstName”, et met à jour la variable “greeting”. Le blog 1 dépend de “greeting”, et est donc exécuté après 2.

Comme j'ai l'esprit tordu, j'ai tout de suite essayé de faire une dépendance cyclique:

let firstName = 'world';
let greeting
$: firstName = greeting + 'hum';
$ :greeting = 'Hello ' + firstName; 
firstName = 'Bob';

Mais… le compilateur l'a détecté et a sorti une erreur. Parfait, il y a des gardes fous !

Je trouve cette illusion, cette magie… fascinante. Le compilateur simplifie énormément le modèle mental. Et en meme temps ca reste une illusion. Le compilateur change le fonctionnement du JavaScript.

J’adore ce fonctionnement, qui me donne envie de l’utiliser. J’espère que c’est votre cas aussi.

A condition de garder la conscience que ce fonctionnement est spécifique à Svelte. Que ce n’est pas comme ça que le JavaScript fonctionne, sans l’aide de Svelte.

Svelte apporte des super pouvoirs au code. Mais ces pouvoirs impliquent… de grandes responsabilités.

Social
Made by kodaps · All rights reserved.
© 2023