Pourquoi pas ReactJS ?
A l’heure actuelle, AngularJS s’impose comme la référence des frameworks web. Son approche “full-stack” (c’est à dire qui contient tout le nécessaire pour construire une application single-page ou “SPA”) séduit et son architecture présente de vraies bonnes idées (modularité, injection de dépendance, …).
La formation Zenika marche d’ailleurs très fort. Le framework s’appuie sur sa communauté et son écosystème de librairies dont certaines sont devenues incontournables (UI-router, UI-Bootstrap, angular-translate, etc.). Mais au-delà de l’écosystème AngularJS, il y a celui du Javascript, plus vaste encore et dans lequel se trouve le produit d’un autre géant du web : ReactJS.
Une autre typologie de projet
AngularJS est très orienté application de gestion, c’est à dire des écrans de liste/détail, pour faire du CRUD sur des entités métier. Des pans entiers du framework sont dédiés à cet usage (support REST, formulaire avec système de validation, filtres i18n) et il est, de fait, très performant dans ce type de projet.
A l’opposé des applications de gestion, sur l’échelle de l’esthétisme et de la “séduction graphique”, on va trouver des sites purement visuels (un site vitrine d’une marque de luxe par exemple) où on va privilégier des technos comme Flash.
React se place exactement entre les deux, c’est à dire sur des projets exigeant à la fois un rendu visuel agréable et un design épuré laissant la place aux actions de l’utilisateur. Ah, comme Facebook ou Instagram par exemple ? Oui, c’est normal.
Un framework orienté Composant ?
React n’est pas un framework full-stack, ce n’est d’ailleurs pas un framework (officiellement du moins) : c’est une bibliothèque orientée Composant. Il est très rapide de s’en convaincre : en arrivant sur la page d’accueil (“Just the UI”) ou voyant le nom des méthodes de l’API. Ainsi, si React doit être comparé à AngularJS, ça doit être uniquement à la partie composant d’AngularJS : les directives.
Or de l’aveu même de l’équipe AngularJS, l’API des directives n’est pas évidente et leur utilisation peu intuitive. La communauté se souvient de la série de slides à ng-Europe annonçant la mort de certains composants dans AngularJS 2.0. Le Directive Definition Object en faisait partie :
L’API de React, elle, va à l’essentiel et peut être résumée en quelques lignes. Dans un composant on va trouver notamment :
Un état,
Des propriétés d’initialisation,
Une méthode render
chargée du rendu du composant, appelée pour chaque changement de l’état (fonctionnement rappelant un peu les states
apparus en Flex 4 pour ceux qui s’en souviennent),
Des méthodes liées au cycle de vie du composant (componentWillMount
, componentDidUpdate
, etc.).
L’état peut être assimilé au scope de la directive AngularJS à ceci près qu’à une modification de l’état correspond un et un seul appel à render
(pas de boucle de digestion) et le binding est unidirectionnel (de l’état vers la vue).
Pour faciliter la réutilisation de composant, React rend possible la définition d’un contrat d’interface. Imaginons l’équivalent React de la directive ngPluralize d’AngularJS. Un tel composant se déclarerait comme suit :
var emailMessages = { '0': 'Aucun email', '1': '1 email', 'other': '{} emails' }
<Pluralize count={nbEmail} values={emailMessages} />
Les attributs count
et values
sont les propriétés du composant Pluralize. Ce dernier ne peut pas fonctionner si elles ne sont pas correctement définies. Ainsi dans la déclaration du composant, on va pouvoir ajouter la clé suivante :
propTypes: { count: React.PropTypes.number.isRequired values: React.PropTypes.shape({ '0': React.PropTypes.string, '1': React.PropTypes.string, 'other': React.PropTypes.string }).isRequired }
Grâce à ce contrat d’interface, le développeur reçoit un message explicite dans sa console en cas de mauvaise utilisation du composant :
Required prop ‘count’ was not specified in ‘Pluralize’.
Message qu’il ne verra même plus lorsque les IDE se baseront sur les propTypes pour fournir une puissante auto-complétion !
Une autre manière de coder
Depuis des années prévaut le principe de séparation des responsabilités entre la vue déclarative en HTML et la logique impérative en Javascript. AngularJS respecte ce principe puisque les templates sont en HTML (et encore, les templates ne sont pas logic-less).
React prend le contre-pied en proposant une manière d’écrire du code déclaratif (type HTML) directement dans le retour de la méthode render
. Le “langage” qui en résulte est le JSX. Il nécessite une compilation en Javascript pour être compréhensible par les moteurs d’exécution Javascript (navigateurs ou NodeJS). Voici une déclaration (simpliste) du composant Pluralize évoqué ci-dessus en JSX :
var CommentBox = React.createClass({ propTypes: { count: React.PropTypes.number.isRequired values: React.PropTypes.shape({ '0': React.PropTypes.string, '1': React.PropTypes.string, 'other': React.PropTypes.string }).isRequired }, render: function() { var value = this.props.values[this.props.count]; if(!value) { value = this.props.values['other']; } // Notez le retour en simili-HTML return (<span>{value}</span>); } });
C’est assez surprenant au premier abord mais ça devient naturel au fur et à mesure qu’on rentre dans la logique “Composant”. C’est agréable de ne plus basculer sans cesse entre les 2 fichiers HTML et JS. Tellement agréable qu’il est finalement dommage que les styles ne suivent pas cette logique (le “CSSX” n’existe pas !).
Les fichiers JSX peuvent rester clairs et concis grâce à l’utilisation de mixins et les tests se retrouvent facilités par cette unification (pas l’intégration HTML/CSS par contre !).
Avec quoi je fais ma SPA ?
C’est vrai qu’un simple bibliothèque orientée Composant ne suffit pas à faire une application single-page. C’est pourquoi les créateurs de React poussent l’utilisation de Flux, un design pattern alternatif au modèle MVC, privilégiant un workflow unidirectionnel plus adapté à une logique Composant.
On entend souvent dire qu’il y a des grosses lacunes dans React comme l’absence de support des appels AJAX. Il est clair que la jeunesse de cette technologie se fait parfois ressentir et certaines librairies / outils n’ont pas le niveau de maturité de leur homologue AngularJS, comme le routeur ou le lanceur de test.
Il faut savoir toutefois que React s’inscrit très bien dans une application découpée en module CommonJS et servie au navigateur via un bundle construit par Browserify ou webpack. Dans le cas du support AJAX, il est possible d’inclure des modules npm offrant une compatibilité navigateur tel que superagent ou http-browerify pour bénéficier d’un support AJAX complet et mature.
A l’inverse, React est capable d’effectuer le rendu d’un composant dans NodeJS. Cela signifie qu’une page de l’application peut être pré-rendue coté serveur et envoyée au navigateur avec le contenu. La page n’est plus une coquille vide mais contient réellement le contenu dans le code source, avec tous les bénéfices que cela peut avoir pour le SEO : c’est l’approche isomorphique.
Conclusion
React a de bons atouts pour trouver sa place dans les frameworks Web. En tant que développeur de composant AngularJS (angular-breadcrumb), j’ai senti un vrai vent de fraîcheur en utilisant React. C’est une bibliothèque orientée Composant et là-dessus il tient ses promesses : puissant et plaisant à coder. Il peut être la base d’une vraie stack de développement d’application front.
Super article ! Je rappelle aussi qu’il y aura la conférence react-europe.org les 2 et 3 juillet avec toute l’équipe de facebook qui sera là avec de grosses annonces surprises prévues 🙂
React ouvre surtout la voie a une programmation purement fonctionnelle et predictible coté front, tout en etant optimisé avec des structures immuables.
A voir la video de David Nolen, auteur de Om:
Grosso modo React utilisé de cette manière n’est plus qu’un enorme template (a la Velocity / Freemarker / Tiles / Thymeleaf whatever) qui transforme un etat applicatif global en DOM de manière pure. Du coup cette transformation n’est plus du tout un probleme, il ne reste plus qu’a se concentrer sur comment organiser son etat global et comment il évolue avec le temps.
Les concepts de React ne s’appliquent pas qu’au DOM. Ils viennent juste d’annoncer React Native pour les applications mobiles. Ils pourraient aussi annoncer ReactSwing dans le future mais j’en doute un peu :p