Alternatives à React

Quelles alternatives à React et pourquoi en choisir une ?

React.js est l'une des bibliothèques les plus importantes de l'histoire de JavaScript. Développée par Facebook (aujourd'hui Meta), elle proposait une approche réactive jusqu'alors très peu utilisée dans les clients web. Ses idées novatrices en matière de gestion d'état et de cycle de vie des composants, couplées à une excellente équipe de développement, lui a permis de se hisser rapidement comme l'une des références incontournables pour tout développer web frontend.

Mais aujourd'hui, l'on a bien plus conscience des limites du modèle de React qui, si il a su se renouveller avec brio, n'en reste pas moins imparfait. Dans cet article, nous vous proposons de découvrir d'autres bibliothèques et frameworks pour remplacer React, avec leurs avantages et inconvénients respectifs.

Qu'est-ce qui ne va pas avec React ?

Malgré son statut de mastodonte dans le monde du JS, React a plusieurs problèmes majeurs qui reviennent de manière récurrente.

Les performances

React utilise un système de DOM virtuel, nommé Virtual DOM (ou VDOM) qui est dérivé du JSX que vous écrivez dans vos composants. Lors de l'exécution, ce VDOM est comparé au DOM réel, et les modifications sont appliquées d'une traite. Cela permets d'éviter d'avoir à remplacer tout le DOM à chaque fois.

Seulement voilà, un VDOM, ça demande des calculs. Calculs qui prennent du temps. Au final, si l'on compare à du JS sans framework (vanilla), les performances d'un composant écrit à la main seront bien plus élevées que celles des composants de React.js.

La taille du runtime

Le runtime de React.js n'est pas des plus légers. Comparé à d'autres frameworks, il est même assez lourd, et c'est un problème car cela nécessite non seulement un transit plus important de données entre le serveur et le client, mais également un temps avant le premier rendu et la première interaction plus élevées. Cela peut causer des problèmes tant en terme d'expérience utilisateur que pour le référencement (SEO) de votre site.

La gestion des effets et les dépendants

Dès lors que vous souhaitez modifier l'état de votre composant après le début de son apparition, vous devez invariablement utiliser useState() couplé à des useEffect() et useCallback() pour indiquer à React.js les endroits où l'état de votre composant est susceptible d'être modifié.

useEffect() et useCallback() nécessitent notamment de fourni un tableau de dépendances indiquant de quelles données votre fonction est dépendante, afin que React sache dans quels cas l'appeler.

Seulement, cela signifie faire très attention aux dépendances utilisées dans les callbacks. Et c'est une source d'erreurs ; même si des lints existent, tout le monde ne les utilise pas, ils ne sont pas parfaits, et ça reste un système optionnel.

L'apparition de nouveaux frameworks

D'autres frameworks sont donc apparus pour essayer de fournir des alternatives à ces problèmes. Vous avez certainement entendu parler d'au moins certains d'entre eux.

Preact

Preact fut l'un des premiers à se poser en alternative de React.js : largement plus léger, il proposait fondamentalement le même fonctionnement que React, en enlevant tout le superflu. On ne retrouvait par exemple pas de support mobile natif dans Preact.

Sa légereté et les outils de compatibilité fournis pour les bibliothèques pure React l'ont projeté sur le devant de la scène et fait rapidement évoluer pour devenir une bibliothèque mature, qui conserve toujours son esprit d'origine, comme l'affiche fièrement la page d'accueil de son site : "une alternative de 3 KB à React avec la même API moderne".

Si vous connaissez React, Preact ne vous dépaisera pas : le fonctionnement est fondamentalement le même, à quelques détails près. On peut finalement considérer Preact comme une version "lite" de React, avec uniquement le coeur par défaut, qui est la partie la plus importante.

Vue.js

Vue.js est apparu comme un concurrent direct à React : proposant un système de templates avec une syntaxe dédiée basée sur HTML plutôt que sur du JSX comme React, elle a connu trois itérations majeures dont l'actuelle est la v3.

Proposant un support complet de TypeScript, une gestion des propriétés des composants simplifiées et une syntaxe particulièrement épurée, Vue.js a rapidement su s'imposer comme acteur majeur de l'écosystème client JavaScript. L'apparition de nouveautés comme la Composition API l'ont rendu plus abordable et moins piégeuse que React.

Voici par exemple un simple compteur écrit avec Vue :

Comme vous pouvez le voir, la syntaxe est très simple et immédiatement compréhensible. Pas de useState, pas de setCount() ou autre, on utilise simplement les références avec ref() directement dans le code comme des variables classiques.

Les styles sont scopés par défaut, ce qui signifique qu'ils ne débordent pas du composant dans lequel ils sont déclarés : si un composant parent employant celui-ci affiche un bouton, il ne sera pas affiché en gras par défaut. Seul les <button> de ce composant vous recevoir le style indiqué. Les composants enfants bénéficient d'ailleurs du même traitement. Notez qu'il est bien sûr possible d'injecter des styles globaux au besoin.

Si vous avez l'habitude de frameworks full-stack tels que Next.js, sachez que Vue propose son propre framework avec Nuxt.js.

Svelte

Svelte est l'une des arrivées plus jeunes dans les frameworks JS, avec comme motivation d'avoir le fonctionnement le plus simple et intuitif possible. Comme Vue.js, il utilise un format custom pour ses templates, couplé à un compilateur performant qui permets d'obtenir d'excellentes performances par l'absence de VDOM.

Là où React et Vue nécessitent d'établir une réprésentation virtuelle du DOM en mémoire, notamment afin de le comparer au DOM réelle et d'y appliquer des modifications de manière optimale, Svelte s'en passe complètement et utilise sa syntaxe et son compilateur pour appliquer les modifications directement au DOM. Cela permets de bénéficier d'un large boost de performances qui peut être significatif selon le contexte.

Voici le même compteur que tout à l'heure, avec Svelte :

Intéressant, n'est-ce pas ? Ici, même pas de ref(): on utilise les variables directement. Pas besoin de balise <template> ou d'attribut scoped pour le style, tout est fait automatiquement par défaut.

Cela permets d'avoir un fonctionnement particulièrement intuitif car aucune des difficultés de React n'est présente ici : toujours pas de useState() ou se setCount(), pas besoin d'un useEffect() ou d'un useCallback(), pas besoin d'un tableau de dépendances. Exemple :

Ici, les callbacks n'ont pas besoin d'être déclarés à l'avance. Ils sont implicites. Le compilateur fait ensuite le travail nécessaire pour calculer ce qu'il faut.

Svelte propose également de nombreuses fonctionnalités pour la gestion des events, du state, etc. et nous vous invitons comme pour les autres frameworks à consulter sa documentation pour en savoir plus.

Un framework full-stack est également proposé sous le nom de Svelte-Kit.

Solid.js

Solid.js est l'un des derniers venus, proposant un fonctionnement plus proche de React avec du JSX mais sans VDOM. La principale différence avec React est que contrairement à ce dernier qui appelle sans cesse la fonction des composants et compare les résultats à chaque fois, Solid utilise une approche où la fonction d'un composant n'est appelée qu'une seule fois au cours de l'entièreté de son cycle de vie. Les changements se sont grâce à un système de signaux qui permettent de ne pas avoir à gérer de tableau de dépendances par exemple. Démonstration :

Ici, on incrément un compteur automatiquement à chaque seconde. Comme vous pouvez le voir, on utilise quelque chose de très similiaire à React : useSignal() (au lieu de useState()), des fonctions de lifecycles comme onCleanup() et on retourne du JSX.

Sauf qu'ici, pas besoin de déclarer de callback dans notre setInterval(). Pas besoin d'utiliser de useEffect(). Pas besoin d'utiliser toutes ces complications de React : tout est géré automatiquement par le compilateur, une fois de plus.

Un simple compteur nous donnerait le code suivant :

Simple et efficace.

Alors, que choisir ?

Tout dépends de votre usage. React reste la bibliothèque la plus suivie, avec de loin le plus large écosystème et le plus de développeurs le maîtrisant déjà. Mais c'est aussi un outil prône aux erreurs, avec des performances limitées qui peuvent être un problème selon le contexte, et qui se base sur une architecture vieillissante - bien que toujours efficace.

On l'a vue, les frameworks tels que Vue, Svelte ou Solid proposent des approches différentes, novatrices, qui tranchent plus ou moins nettement avec React en terme de syntaxe et/ou de fonctionnement, fournissant des performances et une DX (Developer Experience) parfois bien supérieures. Leur écosystème reste bien plus limité (à l'exception de Vue.js qui est aujourd'hui assez étendu) mais aussi plus moderne : les outils créés pour ces frameworks utilisent le gain d'expérience fourni par les anciens, permettant d'éviter nombre d'écueils et de changement d'architecture en cours de route, comme on l'a souvent vu pour React.js.

En somme, aucun framework n'est meilleur que les autres ; le meilleur pour vous restera celui qui est le plus adapté à votre projet. Facilité de trouver des développeurs expérimentés, taille de l'écosystème, qualité de la DX, performances sont autant de facteurs à prendre en compte qui varient considérablement selon l'option que vous choisirez.