En 2020, tout semblait nous montrer que le server-side rendering était mort. Tout le monde utilise React, AngularJS ou Vue pour construire son application. Sauf que moi je ne suis pas d’accord, et que je compte bien jouer le vieux développeur. Bonne lecture
Alors l’architecture d’une application Web basée sur Java/Scala/Kotlin est constituée d’une tranche de pain sur laquelle vous allez étaler d’une part votre plus belle API REST, et d’autre part n’importe quel framework Javascript tant qu’il s’agit soit de ReactJS, d’AngularJS ou de Vue. Voilà. Et vous verrez, tout va bien se passer.
Imaginez : vous tombez dans le coma pendant une semaine. Vous vous réveillez, et votre framework JS favori a disparu, remplacé par un autre framework.
Je fais partie du clan des personnes qui, bien que maîtrisant React ou Angular, pense que le server-side rendering a encore de l’avenir. Nous pourrions en débattre autour d’une mousse : je ne pense pas que tout le monde doit se jeter forcément dans des architectures moite-moite.
Le server-side rendering c’est tout simplement lorsque le rendu de la page HTML+CSS se fait côté serveur, et que le navigateur n’en fait pas une. Vous pouvez ajouter un peu de JS, mais ici point de virtual DOM ou autre. Le serveur génère une page HTML complète, qui part du serveur jusqu’au navigateur. Je sais, cela vous semble dingue, mais c’est comme cela que nous faisions des applications Webs autrefois.
Le client-side rendering permet de construire un site internet ou une application en assemblant le HTML dans le navigateur. Cela évite des aller-retours vers le serveur, on est plus proche d’une application classique. L’interface peut aussi évoluer sans que le serveur évolue. La partie client est un projet à part entière et peut avoir des cycles de mise à jour différents de la partie serveur.
C’est lorque le monde Javascript a commencé à parler de « server-side rendering » que j’ai tiqué. Le Javascript côté serveur ne date pas de la sortie de node.
Il y a fort longtemps, en 1999, je codais en Javascript côté serveur. La technologie Livewire portée par Netscape permettait d’écrire des applications Webs plus simplement que via l’utilisation de CGI-BIN. Javascript était d’abord un langage côté serveur avant d’aller se balader dans votre navigateur Web. C’est papy qui parle, c’était juste pour dire que JS a d’abord été une techno côté serveur.
Je me permets d’emprunter un slide du framework « Unpoly » pour vous expliquer l’une des raisons de ma circonspection quant à la sur-tartinalisation de Javascript et de Java.
En 2005 nous avions l’approche de conserver la complexité uniquement du côté du serveur web. C’est encore possible de nos jours, les frameworks Webs sont justement là pour proposer ces services : routage, authentification, autorisation, contrôle, chargement et persistence de vos données, etc.
Quelques années plus tard, il est possible de créer une application dîtes « cliente » en JS ou Typescript. Les frameworks comme ReactJS ou AngularJS sont justement là pour faciliter l’écriture côté client. Rien que la gestion des dépendances, les pré-processeurs de données, les linters par exemple nécessitent différents outils. Le tout s’intègre très bien avec l’univers node. Vous passez une petite couche de npm ou de yarn, et c’est emballé.
Pour moi, c’est mettre de la confiture des 2 côtés de la tartine.
Le slide ci-dessous résume bien 10 années d’évolution côté Client (aka votre navigateur web) :
Première observation : cela entraîne une duplication de certaines couches logicielles. Dans un projet récent nous avons utilisé Keycloak, un outil open-source qui permet d’authentifier les utilisateurs. Une fois l’authentification effectuée, Keycloak enverra votre visiteur vers votre application Web, avec un jeton sécurisé. Charge alors à votre belle application ReactJS de vérifier le token (ce qu’elle sait faire sans souci). Idem pour votre backend Java, basé sur Quarkus, qui lui aussi devra discuter avec Keycloak. C’est pas compliqué mais cela demande plusieurs technologies différentes, et un peu de savoir-faire pour que tout fonctionne correctement.
Ici le risque c’est la complexité accidentelle… Tout cela car il est nécessaire que votre front-end soit capable d’invalider une session, et de redemander un jeton.
Deuxième observation : l’écosystème JS/Typescript est une communauté à part entière, bien plus large que la communauté des développeurs Java. Or si toi, cher lecteur (chère lectrice) tu viens du monde Java, il te sera difficile de maîtrisier les outils, les frameworks et le niveau nécessaire pour être qualifié de « développeur pas trop pourri côté front« . Regardez le visage circonspect de votre collègue lorsque vous lui demandrez la différence entre yarn et npm… J’ai passé plusieurs mois sur un projet ReactJS et il m’arrivait souvent de voir mes collègues en arrêt sur image sur des trucs de bases… car personne n’avait expliqué « pourquoi » il fallait faire telle ou telle action. On a beau être ceinture noir dans une techno, il sera difficile d’acquerir le même niveau et les mêmes connaissances dès que l’on sort de sa zone de confort. Il y a de très bons développeurs React/Angular/Machin JS. Mais ils n’auront pas vos connaissances côté back pour construire une API et donc il faudra se connecter. Il me semble assez difficile d’être bon partout. Je ne connais pas d’experts universels. Je connais beaucoup de personnes qui pensent être bons partout.
Or si vous ne maîtrisez pas le front et le back, que va-t-il se passer ? Comme la majorité des projets Webs : pas grand chose de grave. Vous aurez l’impression d’avoir un correspondant Allemand à qui il faut rendre visite de temps en temps. Ce sera le développeur Frontend si vous êtes « back » et inversement si vous êtes dev front. Cela nécessitera plus de synchronisation forte et une contractualisation sur les échanges et sur l’api Web. C’est un surcoût. Et parfois, vous vous planterez. Trop/pas assez de donnés. Graphe de data obèse ou anémique… Alors vous mettrez du GraphQL pour que ça se passe mieux mais bon, cela ne pourra pas résoudre la nécessité de dialoguer avec « l’autre développeur ».
Troisième observation et sans faire de trolls : les frameworks évoluent rapidement. Nous sommes sur des cycles de 2 à 3 ans. Prenez ReactJS : un développeur Frontend que je pense expérimenté sur cette technologie, m’a avoué avoir découvert les Hooks sur un projet commun il y a un an à peine. Il suffit d’avoir fait un projet avec React en 2017 pour être obsolète en 2019, avec l’ajout de cette fonctionnalité qui, au passage, est très pratique.
Oh le monde Java ne s’en sort pas mieux, même si les cycles et les évolutions de nos frameworks Webs sont plus lents. Prenez Play Framework v1…. Et bien lorsque Play2 est sorti, ce fut la douche froide pour les vieux de la vieille : Play2 était un autre framework, cousin éloigné de Play1. Cela arrive aussi à des gens biens.
Pourquoi je vous parle d’archéologie ? Je vous parle de ce souci si votre métier est d’écrire des applications Webs « qui durent« . Si votre application est amenée à rester en production 2 ou 3 ans, cela risque de poser un petit souci. Est-ce que le choix de React + SpringBoot ou alors de React 16.8 + Rails 6.0 sera toujours aussi solide dans quelques années ? Le souci n’est pas le choix d’une techno. Le souci c’est d’avoir sélectionné plusieurs technologies. J’ai une pensé émue pour ceux qui avaient tout misé sur Angular 1.x avant que le projet se fasse remplacer quelques années plus tard.
La solution pour se passer d’un framework complet comme React ou Angular existe
Cette approche 100% server-side ne veut pas dire que nous ne pourrons pas utiliser de javascript/typescript ou autre. Cela veut dire que nos pages Webs seront des templates côté backend, et que nous utiliserons un peu de javascript pour « booster » l’expérience utilisateur. C’est pas nouveau sous le soleil de Landernau, il existe des petites librairies JS à même de booster votre application Web garantie 100% « server-side » sans devoir sortir l’artillerie lourde.
Je souhaite vous parler de 2 projets intéressants :
- Unpoly https://unpoly.com/
- Htmx https://htmx.org/
Ces 2 frameworks JS simples permettent d’améliorer l’expérience utilisateur sans casser l’approche « server-side rendering ». Unpoly est un peu plus complet (et compliqué) mais vous permettra de gérer des Forms via AJAX, de charger des fenêtres modales, de gérer les événements de la page, et de construire une application Web à la mode 2020 très simplement. Le projet est moins populaire et moins connu qu’Htmx, mais il mérite un coup d’oeil.
Htmx est encore plus basique, mais permet de traiter un bon paquet de cas d’usages adressés en principe par une application React/Angular/MachinJS.
Si vous devez investir 4h de votre temps, que dis-je, de votre vie de développeur : je vous recommande de regarder cette présentation d’Unpoly et de lire les cas d’usage d’HTMX. Faites moi plaisir : regardez comment cela fonctionne. Vous verrez que lorsque votre application n’a pas l’absolue nécessité d’être une SPA (Simple page application), ces frameworks seront intéressants à connaître.
D’autres librairies (que je n’ai pas testé) :
- Trimming
- StimulusJS (qui vient des équipes de Basecamp / Hey) et qui tourne avec Turbolinks
- Turbolinks/ s’adresse à la navigation et ne casse pas le fonctionnement du navigateur (reload, bouton retour arrière, urls)
- Intercooler.JS there is no need to be complex. Adapté si vous voulez revoir les échanges clients/serveurs. Exemple typique : un lien classique a href pour POSTer un formulaire, sans passer par jQuery.
Conclusion
Je ne suis pas contre les frameworks JS/Typescript ou autre. Je suis contre la complexité, et contre les choix dictés uniquement par ce que savent faire les développeurs dans votre équipe. Si votre dev front ne connaît que React, c’est un souci pour moi. De même, si votre développeur Java refuse de taper une ligne CSS/HTML, c’est aussi un souci pour moi.
Nous ne pouvons pas être expert partout, mais nous devons toujours rester curieux et s’intéresser à ce qu’il est possible de faire.
J’espère que cet article vous permettra de découvrir une façon complémentaire de construire une belle application Web.
Merci Nicolas pour cet article que j’ai pris plaisir à lire!
Le sujet me parle car j’ai été dev Java à l’éqoque où tout le rendu se faisait côté serveur, avant de transitionner en dev front (angular 1 puis react).
J’adore l’approche d’Htmx et Unply (que je découvre au passage). J’aurais aimé avoir ces outils il y a quelques années. Je me souviens avoir implémenté ce genre de navigation entre pages sans rechargement, à base de hacks Jquery… Là c’est vachement plus propre et ça permet d’aller encore plus loin.
Bon après, je ne suis pas 100% d’accord quand tu décris des architectures toujours plus complexe avec le temps. Côté front je veux bien, mais côté back, dans mon expérience ça c’est bien allégé avec la logique d’affichage partie côté front, et des controleurs qui n’implémentent plus que la couche REST.
Oui le front s’est complexifié. Avec des outils de build devenus nécessaires pour gérer tout ce bazar.. Mais les UI sont aussi devenues plus complexes avec des interactions bien plus fines. Le genre d’UI qui semblaient impossible à faire à l’époque où on faisait tout server side.
Apres, c’est sûr que si on utilise on framework JS juste pour afficher du contenu, sans interaction particulière, c’est dommage. Et dans ce cas ce serait plus simple de faire du full server side ou de l’hybride ligth avec Htmx.
Merci Nicolas pour ce billet bien vu. Quelques remarques au fil de l’eau.
Tout d’abord il faut préciser que la notion de « Server Side Rendering » (SSR) n’a pas exactement la même signification sur une SPA aujourd’hui avec des frameworks comme react ou vuejs, qui le proposent, mais concerne plutôt le chargement initial de la page – pour traiter les problématique de premier temps de chargement et de SEO.
Ensuite n’oublions pas que si le front en est là aujourd’hui, c’est à mon avis en partie dû aux backs d’hier… Il ne faut pas oublier qu’en 2005 les « applis Front » JS n’étaient pas réellement considérées puisqu’elles étaient souvent cantonnées à manipuler quelques éléments du DOM et Ajax pour ajouter un peu d’interactivité ou vérifier joliment les formulaires – les libs DHTML étaient alors au top. Et beaucoup de devs back (dans le monde pro, souvent Java) ne portaient pas souvent le front dans leur cœur, étant relativement hermétiques: le JS n’était pas « noble », c’était de la bidouille de langage. Pas mal de devs back qui développaient en JS n’avaient pas l’impression de faire une application. D’ailleurs comment les devs back auraient-ils pu avoir cette impression alors que côté front il n’y avait ni modèle MVC, ni POJO, ni directives « à la taglib », ni jUnit ? Pas sérieux tout ça 😉 Backbone est arrivé en 2010 pour combler un premier trou, puis AngularJS, introduisant MVC, POJO, directives (composants), tests unitaires… et enfin Typescript, ce dernier symbolisant pour moi toute la rigueur qu’on moquait à JS. Bref tout ce qui parlait aux développeurs back et aux concepteurs d’applications. Dès lors tout le monde s’est engouffré là-dedans puisqu’on avait maintenant de quoi faire côté front ce qu’on avait promu pendant des années côté back.
Avec des capacités intéressantes, notamment celle de pouvoir confier le dev du front à une équipe différente de celle du back, une équipe ELLE intéressée et concernée par les problématiques d’UI et d’UX ; autre capacité : avoir su progressivement développer de vrais écosystèmes autour de ces technos, par exemple react permet aussi bien de faire du front que de la VR, ou encore du mobile -> pas mal, non ? Mais effectivement cela s’est fait avec un risque de « complexité accidentelle » qui n’est pas neutre. Et oui aussi, un des effets de bord est qu’on a vu surgir des devs qui se sont déclarés « fullstack » parce qu’ils avaient fait un peu de JS côté back, mais sans pour autant être pleinement capables de penser API ou de penser a minima contrainte d’architecture, ou sécurité. Sur ce point il y a de la formations à faire.
Evidemment, comme pour toute techno jeune, il a fallu apporter quelques améliorations à ces nouveaux frameworks front. Aujourd’hui chaque framework front à sa CLI, et on ne passe plus des heures à configurer son webpack ou son rollup. Et on ajouté le SSR dont on parlait plus haut. Tiens, encore mieux, la semaine dernière react a annoncé « React Server Components » dont la RFC vise à générer le code HTML des composants sur le server. Quelque part dans l’esprit c’est un peu ce que fait Unpoly (j’écris bien « dans l’esprit » et « un peu »). Mais je te laisse consulter en diagonale la RFC (https://github.com/reactjs/rfcs/blob/bf51f8755ddb38d92e23ad415fc4e3c02b95b331/text/0000-server-components.md), perso j’y trouve un grand air de.. JSF! Un éternel recommencement ? Ou la maturité ? On arrive progressivement à refaire côté back en JS l’écosystème qu’on a connu en Java et qui a adressé ces problématiques – peut-être maladroitement, a minima sans faire l’unanimité – il y a bien longtemps. Front et back, même combat ?
Finalement comme souvent il n’y a pas une seule voie possible, que ce soit côté back ou côté front. Comme souvent selon la taille et la complexité de l’appli, les équipes qui vont participer, leur maturité, la maintenance qu’il faudra réaliser, la supervision et la sécurité, il y aura des choix plus appropriés/pertinents que d’autres. A titre perso j’apprécie l’aspect sémantique de Unpoly et ces fragments HTML, mais c’est difficilement applicable dans un quotidien pro fait de consultants qui vont et viennent sur les projets. Et peut-être que demain ce sera webassembly qui mettra tout le monde d’accord…
Pour terminer, je crois que tu pourrais sans peine décliner ton billet en comparant applis monolithes/API vs full micro-services, VM vs Kubernetes, et le meilleur pour la fin (?): appli front « standard » vs les micro-frontends, comme si avoir juste un framework côté front ne suffisait pas 😉
Merci Emmanuel, très bon retour de ta part, je partage ton analyse. Je garde le sujet micro-services : qui / quoi / quand et comment comme idée d’un futur article. En attendant j’avais écris « Micro Service ou Peons Architecture » en 2015, tu peux y jeter un oeil 🙂