Svelte
Mais en fait, Svelte c’est quoi ?
, c’est la nouvelle tendance qui se dessine peu à peu dans le paysage des technologies Front-End. Ce dernier s’est notamment fait connaître avec son concept Write less code, qui consiste à écrire moins de code pour un résultat tout aussi performant. D’ailleurs, c’est l’une des promesses de son créateur Rich Harris, éditeur graphique pour le New York Times, aussi auteur de Ractive.js
Svelte en est à sa version 3. Eh oui, depuis sa sortie en 2016, le Framework qui a très peu fait parler de lui rencontre un franc succès et arrive à s’en sortir face aux mastodontes du marché que l’on connaît tous actuellement. La librairie ne compte pas moins de 28 000 étoiles. Voyez par vous-même : GitHub de Svelte
Svelte
Svelte part d’une idée toute simple : Write less code… mais pas seulement ! À la différence des Frameworks existants, Svelte compile vos composants en code impératif à l’étape de build, autrement dit en code compréhensible par votre navigateur Web. Ceci permet ainsi de charger un seul bundle.js – et bundle.css accessoirement – dans votre page afin que le navigateur se charge uniquement du rendu de votre application. Ce qui ne nécessite pas de Framework à charger au runtime et encore moins de DOM virtuel1
Et à l’usage, ça donne quoi ?
Une syntaxe beginner-friendly
boilerplate à maintenir et une syntaxe qui se veut tout aussi simple d’utilisation. Attachez vos ceintures, nous allons voir tout cela ensemble. Si vous n’avez jamais vu un composant écrit avec Svelte
<style> .pretty { color: purple; } </style> <script> let name = 'World'; </script> <h1 class="pretty">Hello {name}!</h1>
React
import React from 'react'; class Hello extends React.Component { render() { const pretty = { color: "purple" }; return <div style={pretty}>Hello {this.props.name || "World"}</div> } }
Angular
import { Component } from '@angular/core'; @Component({ selector: 'hello', template: '<h1 class="pretty">Hello {{name}}!</h1>', styles: [` .pretty { color: purple; } `] }) export class HelloComponent { name = 'World'; }
Svelte, React et Angular. Comme vous pouvez le voir, avec Svelte : on va à l’essentiel. La définition d’un composant se fait à l’aide des balises familières que sont <style>
et <script>
. Un composant est purement et simplement, la composition d’HTML, CSS et JavaScript. Notez que tout ce que vous définissez dans la balise <script>
est accessible depuis votre template HTML et le CSS contenu dans le composant est encapsulé. Autrement dit, il n’y a aucune chance que vous impactiez d’autres composants. Il est important de préciser que la déclaration de chacun de vos composants doit se faire avec l’extension .svelte
Gestion des entrées et sorties
. Comme chez la plupart de ses pairs, il y a des notions assez récurrentes telles que le fait d’interagir et d’assurer la communication entre composants. Commençons par créer un composant Pokemon.svelte
<script> export let id; export let name; export let species; export let description; </script> <div> <h1>{name}</h1> <p>{description}</p> <div><span>National N°: </span>{id}</div> <div><span>Species: </span>{species}</div> </div>
export
sert à indiquer les propriétés à valoriser afin d’interagir avec notre composant. C’est l’unique moyen dont vous disposez pour déclarer les inputs de vos composants. Une fois celui-ci créé, depuis notre App.svelte
<script> import Pokemon from './Pokemon.svelte'; </script>
le nommage de vos composants se fait uniquement à l’aide du mot-clé import
. Ainsi, ils peuvent être utilisés comme des éléments HTML classiques. Passons maintenant à l’étape suivante qui consiste à valoriser les attributs id
, name
, species
et description
<script> import Pokemon from './Pokemon.svelte'; const pokemon = { id: 888, name: 'Zacian', species: 'Warrior Pokémon', description: 'Zacian is a Fairy/Steel type Pokémon introduced in Generation 8. It is known as the Warrior Pokémon.' }; </script> <Pokemon id={pokemon.id} name={pokemon.name} species={pokemon.species} description={pokemon.description}/>
<Pokemon {...pokemon}/>
on:
. Cependant, émettre un évènement implique qu’il a été au préalable défini en utilisant la méthode createEventDispatcher
<script> import { createEventDispatcher } from 'svelte'; export let id; export let name; export let species; export let description; const dispatch = createEventDispatcher(); function handleClick() { dispatch('selected', { id, name }); } </script> <div on:click={handleClick}> <h1>{name}</h1> <p>{description}</p> <div><span>National N°: </span>{id}</div> <div><span>Species: </span>{species}</div> </div>
createEventDispatcher
qui vous permet de créer des event dispatchers sont des fonctions qui prennent deux arguments : un nom et un payload. Dans notre exemple ci-dessus, l’évènement selected
étant créé, il ne reste plus qu’à s’y abonner de la manière suivante depuis notre App.svelte
<script> [...] function onSelectPokemon(event) { alert(`Pokémon N°${event.detail.id} named ${event.detail.name} is selected`); } </script> <Pokemon id={pokemon.id} name={pokemon.name} species={pokemon.species} description={pokemon.description} on:selected={onSelectPokemon}/>
payload transmis implémente l’interface CustomEvent
3 de l’API JavaScript. Ainsi lors de son émission, nos données id
et name
sont accessibles au travers de la propriété detail
de notre objet event. Et pour terminer, au clic sur notre composant Pokemon
destiny operator
var a = 10; var b <= a + 1; a = 20; Assert.AreEqual(21, b);
Toujours pas ? L’exemple ci-dessus pourrait se traduire en JavaScript de la manière suivante :
var a = 10; var b = a + 1; a = 20; b = a + 1; Assert.AreEqual(21, b);
let a = 10; $: b = a + 1; a = 20; Assert.AreEqual(21, b);
$:
présente quelques limitations, et pour cause : la réactivité d’une instruction n’est déclenchée que par des affectations. Voyons cela d’un peu plus près ! Manipulons, cette fois-ci, un tableau de pokemons
<script> import Pokemon from './Pokemon.svelte'; let pokemons = [ { id: 888, name: 'Zacian', species: 'Warrior Pokémon', description: 'Zacian is a Fairy/Steel type Pokémon introduced in Generation 8. It is known as the Warrior Pokémon.' } ]; function addPokemon() { const newPokemon = { id: 889, name: 'Zamazenta', species: 'Warrior Pokémon', description: 'Zamazenta is a Fighting/Steel type Pokémon introduced in Generation 8. It is known as the Warrior Pokémon.' }; pokemons.push(newPokemon); } </script> <button on:click={addPokemon}> Add a Pokémon </button>
variable « réactive » pokemonName
<script> [...] $: pokemonNames = pokemons.map(pokemon => pokemon.name).join(', ').replace(/, ([^,]*)$/, ' and $1'); </script> <p>In your Pokédex, you have: {pokemonNames}.</p> [...]
Array telles que pop, shift, unshift et splice ne provoquent pas de mise à jour automatique car la référence de l’objet reste inchangée. C’est pour cela qu’il nous faut nécessairement réassigner la variable pokemons
<script> [...] function addPokemon() { [...] pokemons = pokemons; } </script>
Une syntaxe plus concise reviendrait à utiliser la décomposition et ne faire qu’une seule affectation :
<script> [...] function addPokemon() { [...] pokemons = [ ...pokemons, newPokemon ]; } </script>
Et au clic du bouton « Add a Pokémon », nous obtenons le résultat suivant :
Et les performances dans tout ça ?
Svelte, Vue.js, React et Angular
Et donc, au final ?
Svelte se suffit à lui-même et n’a pas besoin de Framework ou bibliothèque tierce pour fonctionner. Avec la pléthore des technologies existant dans le Front-End, vient la question suivante : « Svelte est-il suffisamment mûr pour débuter un nouveau projet ? » Je vous répondrais que la version 3 du Framework est un indicateur de fiabilité assez significatif et non négligeable. D’autant plus que Svelte dispose d’une excellente communauté : 1975 issues cloturées pour 45 pull request. Cerise sur le gâteau, Svelte est également compatible avec Jest et Storybook, respectivement pour exécuter vos tests unitaires et constituer votre bibliothèque de composants. Il est aussi intéressant de noter l’intégration simple qui est faite avec Webpack afin de faciliter le développement et déploiement de vos applications. Ce qui démontre au final que Svelte
[1]: Rich Harris, Virtual DOM is pure overhead, Svelte (2018).
[2]: Mozilla Developer Network, Spread syntax, MDN web docs (2020).
[3]: Living Standard, Interface CustomEvent, DOM (2020).
[4]: Paul Stovell, What is Reactive Programming?, Paulstovell (2010).