- En migrant mux.com et docs.mux.com vers React Server Components, Mux a constaté que la séparation entre l’exécution serveur et client a un impact direct sur la taille du bundle et le coût de l’hydration
- RSC permet aux composants de récupérer directement des données côté serveur et de streamer le résultat, afin d’afficher d’abord une partie de l’écran même en présence d’appels de données lents
- Les principaux obstacles de la migration réelle ont été la non-prise en charge de CSS-in-JS, les limites de React Context dans les Server Components, et la complexité liée au suivi permanent de la frontière serveur/client
- Dans l’app directory de Next.js 13, les composants sont par défaut des Server Components, et une adoption progressive est possible en déplaçant peu à peu
use clientde la racine vers le bas de l’arbre - Les patterns comme Suspense,
loading.js, le maintien de bibliothèques côté serveur uniquement ouserver-onlydoivent être appliqués avec prudence, seulement là où les gains de performance sont nécessaires, en tenant aussi compte du coût cognitif pour l’équipe
Le périmètre migré par Mux vers RSC
- À l’occasion de la refonte de son site de documentation et de son changement de marque, Mux a migré mux.com et docs.mux.com vers les Server Components
- React Server Components peut être appliqué à de vraies bases de code et peut valoir le coup, mais il s’accompagne aussi de contraintes et de complexité
- Ce retour d’expérience explique pourquoi RSC est nécessaire, où il est adapté, dans quelles situations il devient délicat, et comment l’introduire progressivement dans une base de code réelle
Le problème visé par RSC après CSR, SSR/SSG
- Les premiers modes de rendu serveur, avec des technologies comme PHP, récupéraient les données et exécutaient les traitements CPU lourds côté serveur, puis envoyaient au client un HTML léger
- Le CSR/SPA envoyait le code de rendu au client sous forme de JavaScript, ce qui permettait de gérer rapidement les interactions, mais ses faiblesses apparaissaient lorsque les moteurs de recherche n’exécutaient pas JavaScript, lorsqu’il fallait garder des secrets côté serveur, ou sur des appareils peu puissants et des connexions lentes
- Le SSR/SSG, avec des outils comme Next.js et Gatsby, consiste à générer côté serveur à la fois le HTML et le JavaScript, puis à les envoyer au client
- L’utilisateur peut voir le HTML immédiatement
- Une fois JavaScript chargé, le site devient interactif
- Les moteurs de recherche peuvent aussi lire le HTML
- Les approches SSR/SSG existantes conservent toutefois un coût
- La plupart du JavaScript utilisé pour générer la page est envoyé au client, qui doit le réexécuter pour l’associer au HTML via l’hydration
- Si le rendu serveur prend du temps à cause d’appels lents à la base de données ou de l’exécution d’une grande quantité de code, l’utilisateur doit attendre
Ce que React Server Components change
- Les React Server Components sont des composants React exécutés côté serveur, et non côté client
- Un framework compatible RSC permet de séparer explicitement l’endroit où le code s’exécute
- Server Components : code qui doit s’exécuter uniquement côté serveur
- Client Components : code qui doit s’exécuter côté client
- Lorsque le lieu d’exécution est séparé, la quantité de JavaScript envoyée au client diminue, tout comme le travail à effectuer pendant l’hydration
- Un Server Component peut récupérer directement des données à l’intérieur du composant
- Il peut utiliser des bibliothèques Node ou
fetch - Cela permet de réduire le modèle consistant à tout récupérer au niveau de la page avec
getServerSideProps, puis à faire descendre les données via des props - Cela réduit aussi les cas où il faut gérer des états de chargement complexes avec
useEffect
- Il peut utiliser des bibliothèques Node ou
- Une fois la récupération de données terminée, le Server Component peut streamer le résultat vers le client
- Le reste du site peut être affiché d’abord pendant que l’on attend un composant lent
- Il est aussi possible de récupérer des données côté serveur en réponse à des actions utilisateur côté client et de streamer la réponse, mais cela relève à proprement parler de React Actions, et non de RSC
Les aspects délicats de RSC
- CSS-in-JS ne fonctionne actuellement pas avec les Server Components
- Dans la migration de Mux vers RSC, le passage de styled-components à Tailwind CSS a représenté la plus grosse part du travail
- Une base de code qui dépend fortement de CSS-in-JS nécessitera une migration séparée
- React Context n’est accessible que depuis les Client Components
- Pour partager des données entre Server Components sans props, il faudra probablement utiliser des modules classiques
- Les Server Components ne disposent pas d’un bon mécanisme pour limiter des données à un sous-arbre précis d’une application React
- Sur le site de documentation de Mux, cela n’a pas posé de gros problème, car les zones qui utilisaient Context étaient très interactives et devaient de toute façon être envoyées au client
- Sur le site marketing, le partage du thème a posé problème
- Chaque composant du pre-footer devait savoir qu’il se trouvait sur un fond vert afin de pouvoir utiliser une bordure vert foncé
- Mux a contourné le problème en s’appuyant largement sur les propriétés personnalisées CSS au lieu de Context
- RSC apporte de la flexibilité sur le lieu d’exécution et la récupération de données, mais augmente aussi la complexité
- Les nouveaux développeurs doivent constamment vérifier « ce qui s’exécute côté serveur et ce qui s’exécute côté client »
- À chaque PR, des retours peuvent apparaître sur du code envoyé inutilement au client
- Pendant le développement, il était fréquent d’ajouter des
console.logpour vérifier si les logs venaient du serveur ou du navigateur - Le caching ajoute lui aussi une complexité propre
Le mode d’utilisation de base de RSC dans Next.js 13
- Au moment de la rédaction, l’implémentation RSC prête pour la production est l’app directory de Next.js 13
- Dans l’app directory de Next.js 13, les composants que l’on écrit sont par défaut des Server Components
- Par défaut, le code de la page n’est pas envoyé au client
- Seul le HTML est transmis au client
- En ajoutant
asyncà un Server Component, on peut récupérer des données directement à l’intérieur du composant - Un Server Component dont la récupération de données est lente peut être entouré de
React.Suspense- Une UI de fallback est d’abord affichée côté client
- Une fois que le serveur a récupéré les données et terminé le rendu, le composant résultant est streamé
- Une boundary Suspense peut servir non seulement au streaming de données, mais aussi à la selective hydration, qui ajuste la priorité d’hydration de certaines zones en fonction des interactions utilisateur
- Le code qui doit s’exécuter côté client ajoute
"use client"en haut du fichier- On l’utilise pour les composants qui ont besoin d’état côté client et d’interactions, comme un listener
onClickouuseState - Tous les composants importés par un composant marqué
"use client"sont eux aussi envoyés au client
- On l’utilise pour les composants qui ont besoin d’état côté client et d’interactions, comme un listener
- Les bibliothèques qui ne prennent pas en charge RSC peuvent être importées dans un Client Component afin d’être incluses dans le bundle client
- L’exemple est un composant
ClientMuxPlayerqui encapsule@mux/mux-player-react
- L’exemple est un composant
Critères de choix entre Server Component et Client Component
- Les Server Components conviennent au code qui n’a pas besoin d’être envoyé au client
- Rendu du corps d’un article de blog
- Tâches coûteuses comme la coloration syntaxique de blocs de code
- Récupération de données
- Les Client Components conviennent aux UI qui réagissent aux entrées utilisateur ou dont l’état change avec le temps
useState- Listeners d’événements
- Interactions côté client
- Si toute l’application est composée de Client Components, elle se comporte de manière proche des frameworks SSR existants
- Il n’est pas nécessaire de convertir toute l’application d’un coup en Server Components : on peut les introduire progressivement là où le gain est le plus important
Trois étapes pour les introduire progressivement dans une vraie base de code
- Le playbook utilisé par Mux comporte trois étapes
- Ajouter la directive
"use client"à la racine de l’application - Déplacer la directive aussi bas que possible dans l’arbre de rendu
- Appliquer des patterns avancés lorsque des problèmes de performance apparaissent
- Ajouter la directive
- À l’étape 1, Mux a ajouté
"use client"aupage.tsxde plus haut niveau dans Next.js 13 afin que l’application continue de fonctionner comme avant - Si une récupération de données côté serveur est nécessaire, on ajoute un Server Component comme parent du Client Component
- Le Server Component récupère les données
- Les données récupérées sont transmises au Client Component via des props
- Cela peut remplacer le rôle de l’ancien
getServerSideProps
- À l’étape 2,
"use client"est déplacé du composant de plus haut niveau vers des composants enfants- Pour un
<Title />qui n’a pas besoin de code client, on peut supprimer la directive et l’envoyer sous forme de HTML pur - Pour un
<Player />qui a besoin de code client, une erreur se produit, donc"use client"doit être conservé
- Pour un
- Cette approche pousse à envisager les Server Components pour les nouveaux composants et les refactorings existants, et aide à réduire partiellement la taille du bundle
Patterns appliqués en cas de problème de performance
- Le site de documentation de Mux est en grande partie généré statiquement, mais la sidebar du changelog est récupérée depuis le CMS
- En entourant la sidebar avec Suspense, le reste de l’application n’a pas besoin d’attendre la fin du fetch CMS
- La convention loading.js de Next.js 13 utilise aussi Suspense et le streaming en interne
- Pour garder de grosses bibliothèques côté serveur, il faut ajuster le placement des Client Components et des Server Components
- Par exemple, Mux conserve côté serveur la bibliothèque de coloration syntaxique Prism
Comment mélanger un Server Component dans un Client Component
- Les composants importés par un Client Component deviennent eux aussi des Client Components
- Si l’on veut placer un Server Component comme enfant d’un Client Component, il ne faut pas l’importer, mais le passer via
childrenou via des props- Le Server Component est rendu côté serveur
- Le résultat sérialisé est transmis au Client Component
- La mauvaise approche consiste à importer directement un Server Component depuis le fichier d’un Client Component
- La bonne approche consiste à remonter jusqu’au Server Component parent le plus proche, puis à passer le Server Component au Client Component comme enfant ou comme prop
Impossible de diviser un même fichier moitié serveur, moitié client
- Il est impossible de faire d’une moitié d’un fichier un Server Component et de l’autre moitié un Client Component
- Mux utilise souvent un pattern qui divise une fonctionnalité en deux fichiers
CodeBlock.server.js: importe une grosse bibliothèque de coloration syntaxique et effectue le rendu côté serveurCodeBlock.client.js: utiliseuseStateetonClickpour permettre à l’utilisateur de changer d’exemple de code
- Les exemples rendus côté serveur sont transmis au Client Component via des props, de sorte que le travail réservé au serveur ne passe pas dans le bundle client
- Si
CodeBlock.server.jsest réexporté depuisindex.js, l’utilisateur peut simplement importerCodeBlocksans se préoccuper de la séparation interne serveur/client
Garantir qu’un code ne s’exécute que côté serveur
- Au début, Mux ajoutait des
console.logpendant le développement pour vérifier si les logs sortaient côté serveur ou côté navigateur - Pour garantir que du code réservé au serveur ne soit pas inclus dans le bundle, on peut importer le package server-only
server-onlyest utile pour éviter qu’une grosse bibliothèque ou une clé secrète ne soit déplacée au mauvais endroit- Next.js fournit des protections pour empêcher que des variables d’environnement soient incluses par erreur dans le bundle navigateur
- Placer
server-onlyen haut d’un fichier aide aussi à la maintenance- Les mainteneurs voient immédiatement que ce fichier s’exécute côté serveur
Coûts et bénéfices à prendre en compte avant l’adoption
- React Server Components n’est pas une fonctionnalité gratuite
- Les coûts ne se limitent pas aux contraintes de CSS-in-JS et de React Context ; ils incluent aussi :
- La compréhension du lieu d’exécution serveur ou client
- La compréhension de l’hydration
- Les coûts d’infrastructure
- La complexité du code liée au mélange de Client Components et de Server Components
- Cette complexité augmente la surface par laquelle des bugs peuvent entrer et réduire la maintenabilité du code
- Les frameworks réduisent la complexité, mais ne la suppriment pas
- Les bénéfices attendus sont les suivants
- Une taille de bundle plus faible
- Une exécution plus rapide
- Des améliorations de performance importantes pour le SEO
- Des patterns avancés de chargement de données pour les sites complexes et riches en données
- Si l’équipe est prête à supporter le coût cognitif supplémentaire et que les gains de performance sont suffisants, RSC peut être un bon choix
1 commentaires
Avis Hacker News
Avec le rendu côté serveur, le client reçoit du HTML qu’il peut voir immédiatement
Je l’ai ressenti aussi : quand on met un fichier en texte brut sur le serveur, il est transmis assez vite au navigateur
Si on ajoute un autre fichier en texte brut se terminant par
.css, le navigateur sait comment le traiter, et les éléments du premier écran peuvent bouger et devenir plutôt agréables à regarderC’est une astuce sympa, mais cela reste secondaire par rapport à du contenu utile lisible dès le premier écran
Je ne sais pas comment « ajoutons des fonctionnalités pour rendre l’hypertexte plus puissant » est devenu « maintenant, avec ce gros tas de fonctionnalités incohérentes, débrouillez-vous pour implémenter des applications utilisables »
Avant de se lancer dans RSC, mieux vaut faire une pause
Quoi que vous essayiez de construire, ce sera beaucoup plus facile, rapide et scalable avec un vrai framework full-stack ou un framework web classique
Rails/Django/Laravel/… avec Turbolinks/Htmx/…, ou même juste un peu de JavaScript côté client saupoudré là où il faut
Si vous connaissez Elixir/Phoenix, vous pouvez aussi cumuler plusieurs avantages
Peu importe le nombre de gens qui tweetent dessus, il ne faut pas aller plus loin avec RSC
Les personnes ayant moins de 10 ans d’expérience dans le secteur vont retomber sur les problèmes de base qu’on connaissait déjà avec les anciens sites vanilla PHP, et j’ai même déjà vu des hooks SQL inline dans des composants React
Cette fois, il y a en plus bien davantage de complexité accidentelle
Gardez la tête froide, sortez vite un vrai produit et gagnez de quoi vous payer une Lamborghini
CORBA consiste à mélanger des composants locaux et distants ; c’est mature et cela fonctionne dans plusieurs langages
Alors pourquoi tout le monde ne l’utilise-t-il pas ? La plupart des développeurs d’aujourd’hui n’en ont probablement jamais entendu parler
Si vous voulez créer une autre architecture de composants distribués, il faut étudier pourquoi CORBA et ses descendants ne se sont pas largement imposés
L’indice, c’est que les frontières de composants cachées créent de la complexité cachée
Pendant ce temps, les camps « HTML rendu serveur » et « HTML rendu client » fonctionnent tous les deux très bien
Je trouve qu’on a beaucoup de chance de pouvoir utiliser ces deux options pour chaque projet web
J’espère que le travail sur RSC ne brouillera pas le support de React pour les applications à rendu purement client
À moins d’avoir absolument besoin d’une application front-end riche progressive complète, LiveView prend en charge la plupart des cas via des composants côté serveur, avec un minimum de JavaScript
En plus de cela, chaque utilisateur dispose d’un thread côté serveur, ce qui permet de pousser activement les changements vers le front-end de l’utilisateur sans écrire de gestionnaires JavaScript explicites
On dirait que l’industrie souffre d’une amnésie par cycles de 10 ans
Il y avait de très bonnes raisons de s’éloigner des UI rendues côté serveur
Bien sûr, l’argument du référencement existe toujours, mais si c’est votre préoccupation, faites simplement un site traditionnel avec des templates serveur
La grande majorité des applications monopage n’ont absolument pas besoin de SSR ni de sa complexité
Les premières interfaces du dashboard étaient entièrement rendues avec Phoenix, et seules les pages nécessitant des interactions client vraiment avancées embarquaient React séparément
Comme notre premier produit était un dashboard d’analytique, cette situation a rapidement fini par concerner presque tout le dashboard, et il était naturel de migrer vers une application monopage complète en s’appuyant sur l’API que nous exposions déjà à nos clients
C’était en 2016, donc LiveView n’existait pas encore, mais même si nous reconstruisions ce produit aujourd’hui, je ne suis pas sûr que nous prendrions une autre décision
L’article de blog concerne l’application qui alimente le site marketing public, avec des exigences assez différentes, mais je voulais dire que nous aussi, nous utilisons et apprécions Elixir/Phoenix
J’ai l’impression de vieillir
Les frameworks d’aujourd’hui sont trop gros et trop complexes
Même un simple « Hello world » web nécessite un énorme pipeline de build et de compilation, et maintenant on y ajoute même des composants côté serveur
Je me demande vraiment quel est le niveau d’overhead
Je ne sais pas combien de couches de code de frameworks frontend et backend il faut traverser juste pour exécuter un exemple Hello world
Je vais revenir à un framework de composants tout simple de 10 Ko, qui se reconstruit quand on appuie simplement sur F5
C’est une forme d’optimisation prématurée pour des fonctionnalités sophistiquées qui arriveront peut-être plus tard
C’est un peu comme dire qu’il faut embaucher un ingénieur pour prélever des carottes et faire de la modélisation sismique avant de construire un poulailler
Les jeunes développeurs commencent maintenant à le voir
Comme nous avons abandonné des horreurs comme SOAP et XML pour passer à des technologies plus simples et plus faciles à utiliser, cette génération réapprend elle aussi que la complexité est nocive
Peut-être que le développement logiciel redeviendra amusant pendant quelques années, avant que la nouvelle génération ne remette tout en désordre
Un pipeline peut être aussi complexe ou aussi simple que nécessaire selon le cas d’usage
On peut faire avec seulement des fichiers statiques, avec un petit Makefile qui lance une seule commande
esbuild, ou avec une énorme configuration Webpack et 30 pluginsOn peut choisir librement selon les exigences et la complexité de ce qu’on veut construire
De plus, évaluer un outil selon la facilité à créer un simple Hello world n’est utile que si le travail consiste effectivement à créer ce genre d’appli
Quand le SSR ou ses dérivés entrent dans la conversation, je me demande toujours si cela n’ajoute pas inutilement de la complexité
Les composants React rendus côté serveur donnent l’impression d’aller trop loin et d’aller à l’encontre du flux naturel de l’expérience développeur
Si la complexité de l’application double, que les pièges de codage se multiplient, que les développeurs sont ralentis et déboussolés, et que le seul gain est une petite amélioration des performances, je me demande si cela en vaut la peine
Les anciens sites PHP et les applis Rails sans single-page app ont très bien fonctionné pendant longtemps
J’ai vécu ça en créant une nouvelle application avec Next.js et la nouvelle structure de répertoire
appPremièrement, il est difficile de déduire ce qui se passe sur le serveur et ce qui se passe sur le client
Pour le savoir, il faut enquêter, mais quand on écrit du code rapidement, on finit souvent par ne pas trop s’en soucier
Un petit changement peut facilement faire basculer soudainement une grande partie d’une page du serveur vers le client
Je sais qu’avant la sortie finale il faudra faire une validation prudente et chronophage page par page, et ce n’est pas réjouissant
Deuxièmement, une bonne partie des bibliothèques React existantes utilisent des hooks, donc elles supposent s’exécuter côté client
À cause de cela, du code peut être entraîné côté client
L’objectif de se battre avec ce nouveau paradigme, c’est le rendu côté serveur pour un chargement rapide et l’optimisation pour les moteurs de recherche ; si les bibliothèques importées ne coopèrent pas bien, c’est complètement gâché
Troisièmement, le nouveau paradigme du répertoire
appde Next.js contient des bugsIl est encore récent et très complexe, si bien que les routes dynamiques, les routes parallèles et leurs interactions peuvent complètement casser
J’ai moi-même ouvert une issue sur le GitHub de Next.js, et beaucoup de commentaires « moi aussi » s’y sont ajoutés
Une des approches que j’utilisais a récemment été corrigée par un développeur de Vercel, mais j’avais déjà choisi une autre approche pour la contourner
Le plus agaçant, c’est que l’environnement de développement utilise de la magie de chargement paresseux et de cache
On dirait qu’il essaie de calculer les différences entre les pages et d’envoyer des mises à jour partielles via quelque chose comme des WebSockets, mais cela peut se casser complètement et devenir irrécupérable
Parfois, une recompilation déclenche une communication quelconque du serveur vers le client, et quand je reviens à l’onglet Chrome, celui-ci est totalement bloqué, au point qu’il faut tuer le processus via le gestionnaire de tâches de Chrome
Globalement, c’est encore très récent et il y a beaucoup d’angles rugueux
Beaucoup de hooks fonctionnent aussi côté serveur et, en réalité, ne font rien d’autre qu’initialiser des valeurs
Il est amusant de constater que PHP et JavaScript avaient en fait des syntaxes quasiment identiques
La différence se limitait à peu près au symbole
$ou au mot-clévar, mais NodeJS disait : « nous voulons exécuter du JS côté serveur »Et 15 ans plus tard, JavaScript a fini par rattraper son retard et ressemble en pratique à PHP, avec davantage d’abréviations et une courbe d’apprentissage plus raide
Bien sûr, streamer des données depuis le serveur vers des composants client avec Suspense, c’est sympa
J’utilise NextJS 13, et j’aime le fait qu’il rende le SSR aussi simple que ce que PHP permet depuis toujours ; je le recommande vivement
Quand les gens parlaient de « fractale de mauvaise conception », c’était justifié à 100 %, et il était légitime d’aller chercher ailleurs pour résoudre le problème
Aujourd’hui, PHP est un bien meilleur langage et mérite qu’on y rejette un œil, mais il ne faut pas faire comme s’il avait toujours été aussi bon qu’aujourd’hui
Et il ne faut pas juger NodeJS à l’aune de l’écosystème React
L’énorme quantité d’API et de wrappers nécessaires pour faire tourner des systèmes basés sur React relève de la responsabilité de la communauté React
C’est un syndrome de Stockholm typique
Beaucoup d’avancées modernes ont été rendues possibles d’abord parce que les navigateurs se sont améliorés
Plutôt qu’un retour complet à la case départ, c’est plutôt un amas qui, vu de très loin, ressemble à un cercle
D’un côté, c’était innovant en ce que son modèle de concurrence permettait de construire des backends plus rapides, mais il lui manquait beaucoup de fonctionnalités des langages backend établis comme Java ou PHP, et beaucoup de patterns ont donc été réinventés
Le langage lui-même a mis des années à atteindre le niveau de « sûreté » que Java possédait déjà et vers lequel PHP se dirigeait
Des technologies éprouvées et standardisées comme XML, et les garanties contractuelles qu’il pouvait apporter, ont aussi été abandonnées au motif qu’elles étaient lourdes, ou que JSON était plus agréable à lire et à écrire pour les humains
J’ai le sentiment que l’abandon de XML nous a fait perdre beaucoup de temps et d’efforts
La documentation des API REST/JSON reste pénible
Il y a 20 à 25 ans, on pouvait déjà générer des modèles de données et des parseurs à partir de payloads XML
Je ne sais toujours pas ce qui posait tant problème avec XML
Sur le fil, c’était un peu plus lourd que JSON, mais c’était un problème résoluble en utilisant la compression ou en le transformant en protocole binaire avec EXI (https://www.w3.org/TR/exi/)
Je ne sais pas si EXI s’est vraiment imposé, mais à l’époque, sachant combien de XML circulait, j’avais placé pas mal d’espoirs dedans
À l’époque, les entrées-sorties non bloquantes apportaient un gros gain de performances
Mais dans l’esprit des développeurs modernes, on dirait que c’est relégué au rang d’outil idiot qui recrache du JSON ou héberge des toolchains
On utilise sans doute ce qu’on connaît, mais utiliser React pour un site de documentation, au lieu d’un générateur de site statique ou d’un CMS prêt à l’emploi avec cache, ressemble à du gaspillage
Du point de vue des développeurs, React peut être plus amusant
Stripe a lancé le mouvement consistant à afficher des fragments de code contenant les clés API du compte, pour pouvoir tester immédiatement
Les sites de documentation frontend incluent presque toujours des exemples exécutables que l’on peut manipuler directement dans la documentation
Le bootstrap d’un nouveau projet est tellement simple et rapide, littéralement plus facile que de démarrer un projet en pur HTML
Qu’est-ce que je rate ?
Au passage, je suis sincèrement curieux de connaître le point de vue des personnes qui votent contre
C’est du contenu statique ; je ne comprends pas pourquoi on ne génère pas simplement du HTML avec un peu de JavaScript pour la barre de recherche
La raison d’utiliser React est d’avoir un seul langage sur l’ensemble du frontend
On peut éviter d’avoir certains qui utilisent React pour un site et d’autres Gatsby/Hugo pour un autre
Next.JS peut faire la même chose que Gatsby/Hugo, avec plus de fonctionnalités, et il est basé sur React
Je suis assez vieux pour me souvenir de l’époque où le serveur rendait tout, et où CSS et JavaScript servaient à enrichir la page rendue
Le Web est devenu un endroit trop sombre et sur-ingéniéré
C’est presque difficile à croire
C’est pourquoi ma façon de construire des apps consiste à commencer par le rendu serveur, puis à enrichir ensuite
Les menus déroulants repliables ou le glisser-déposer en jQuery sont des fonctionnalités appréciables, mais je me souviens aussi très nettement de l’enfer de la gestion d’état à l’époque de JS/jQuery, et je n’ai pas envie d’y retourner
Je plaisante : ma première page Geocities était juste du HTML avec des choses comme un compteur de visites ou une balise marquee
Ma première application/projet PHP à l’école n’utilisait pas encore JS non plus ; on utilisait des frames pour les menus et en-têtes statiques, et les données étaient simplement envoyées au backend via des soumissions de formulaires
Il y a eu cette époque
Lors de mon premier stage d’un an intégré au cursus universitaire, on utilisait un backend Java, des templates JSX pour la couche de présentation, et PrototypeJS pour des choses comme les boîtes de dialogue ou les accordéons animés
À l’époque, une animation, c’était « modifier la hauteur de cet élément plusieurs fois par seconde »
Dans mon premier emploi, j’ai beaucoup utilisé JS pour enrichir les pages, par exemple l’ajout au panier ou les carrousels d’images, et c’était l’ère jQuery
Dans le poste suivant, nous avons très mal construit avec BackboneJS une UI permettant à des employés du support client de consulter des systèmes comme SAP
Le travail d’après consistait aussi à refaire avec BackboneJS un frontend de banque d’investissement destiné aux clients
C’était un cas d’usage très adapté à ce qu’on appelait alors une application monopage
Il n’y avait pas besoin d’optimisation pour les moteurs de recherche, le rendu purement frontend était suffisamment rapide, c’était centré sur les API, et c’était l’époque où les gens réalisaient qu’on pouvait utiliser les mêmes API pour le Web et le mobile
À mon avis, les outils de développement web n’ont jamais été meilleurs qu’aujourd’hui, et l’expérience utilisateur s’est énormément améliorée au fil des années
Ce que nous appelions AJAX est passé d’un petit gadget sympathique à un élément de base du quotidien sous forme de composants client et d’applications monopages
Le serveur reste puissant si on le souhaite, mais pour les apps interactives comme les dashboards, cartes, jeux, forums, suites bureautiques ou IDE en ligne, disposer de capacités solides côté client est une bonne chose
Cela a permis une migration massive des apps du quotidien, autrefois des applications desktop sur mesure pour chaque système d’exploitation, vers une plateforme universelle couvrant tous les ordinateurs portables et de bureau
Bien sûr, cette puissance a exigé davantage de complexité
Écrire un blog ou une landing page en HTML/CSS est très différent de créer une application web complète
Angular et React ont été créés pour aider à développer des apps plusieurs fois plus complexes qu’auparavant, à une époque où le runtime JS et le langage lui-même étaient bien plus primitifs que les langages côté serveur de l’époque
À la fin des années 2010, il y a eu une période vraiment pénible où divers frameworks JS ne résolvaient chacun qu’une toute petite partie du problème
Aujourd’hui, c’est moins le cas
Next a gagné et est devenu le choix par défaut, et c’est mérité
Il fournit le bon niveau d’abstraction pour des apps de complexité moyenne, et permet de bien mélanger rendu côté serveur et pages côté client
Les React Server Components rendent cette séparation plus propre et en font un concept de première classe
Mais cela n’a de sens qu’au-delà d’un certain niveau de complexité
Si vous n’en avez pas besoin, ne les utilisez pas
Pour un blog ou un site de documentation essentiellement statique, il existe des architectures plus simples
On peut toujours écrire du HTML et parsemer juste quelques lignes de JS selon les besoins, et pour la plupart des petites entreprises, WordPress ou Wix peuvent aussi convenir
Mais si vous construisez une app plus complexe, React est vraiment un rêve par rapport à l’ancienne approche consistant à faire un aller-retour serveur pour chaque interaction mineure, recalculer l’UI et renvoyer toute la page HTML à chaque fois
Cette approche faisait perdre le contexte, la position dans la page, les formulaires à moitié remplis, etc., encourageait à utiliser les données de formulaire comme état, et faisait souvent perdre son travail après un clic accidentel sur retour arrière ou à cause de pannes serveur fréquentes avant l’arrivée d’une mise à l’échelle cloud facile
À mon avis, ce n’est de la sur-ingénierie que lorsqu’elle est mal appliquée
Dans les bons cas d’usage, ces outils sont vraiment utiles, et parfois indispensables
Le point regrettable est peut-être qu’on les enseigne trop et qu’on encourage leur usage même dans des situations où ils ne sont pas nécessaires, voire nuisibles
Au final, il faut utiliser l’outil adapté à la tâche
Je ne cherche pas à pousser React plutôt que Vue, Svelte ou HTMX ; je veux simplement dire que la complexité côté client a aussi son utilité
J’ai l’impression que React peine à rattraper des alternatives plus modernes, plus simples, plus rapides et moins coûteuses
Mais au lieu de corriger les problèmes fondamentaux — les rerenders, la mémorisation fréquemment nécessaire, les abstractions qui fuient — React devient plus complexe
Je comprendrais cet effort si le résultat final était excellent, mais ce n’est pas le cas
React est plus lent en conditions réelles que ce que montrent les benchmarks, et Next est encore pire
J’ai vu récemment beaucoup de sites web très lents construits avec Next
Je ne comprends vraiment pas
Si l’équipe React veut améliorer React, elle doit corriger le cœur
Il y a maintenant trop de dépendances dans l’écosystème, ça casserait tout
Target.com, Walmart.com, Microsoft Teams et d’innombrables autres sites sont en React
Il existe aussi un énorme écosystème de composants et des entreprises construites dessus
Les concepts de base sont cassés, mais les corriger voudrait dire risquer de casser tout le reste
Si c’est pour tout casser de toute façon, autant utiliser autre chose
Aujourd’hui, la masse des dépendances fait qu’on reste attaché à React et qu’il faut continuer à avancer avec
React rerend par défaut et demande de s’en extraire, tandis que Vue, Solid, Preact et Svelte adoptent tous une approche où l’on opt-in là où c’est nécessaire
C’est l’une des raisons principales pour lesquelles il est difficile à utiliser correctement et vulnérable à certains types de bugs
Même si, en surface, cela ressemble à du JavaScript ordinaire, il faut constamment se demander s’il faut s’en extraire, alors que dans les autres frameworks ces bugs sont rares, voire quasi inexistants
https://react.dev/blog/2023/03/22/react-labs-what-we-have-be...
Je ne comprends pas pourquoi on utilise maintenant React côté backend pour rendre du HTML
Est-ce qu’on veut revenir 10 ans en arrière ?
Ces temps-ci, je passe souvent de Svelte aux templates Django, et avec Svelte l’expérience est bien meilleure, ne serait-ce que parce qu’il connaît le DOM
Je n’ai jamais vu ça dans un système de templates qui ne soit pas en JS
J’ai aussi connu PHP, jQuery, etc.
En plus, si le frontend est en React, il est bien plus simple de regrouper toute la génération de HTML au même endroit
Avec, en plus, la prise en charge du typage statique
Je ne cherche pas à défendre RSC ou React comme la meilleure solution de tous les temps, mais certaines des objections ici sont un peu immatures
Les bénéfices de React/RSC ne sont pas techniquement identiques au fait qu’un serveur renvoie du HTML/CSS et un peu de JavaScript
Cela reste une seule application, avec une façon plus intelligente de gérer la frontière client/serveur par rapport au SSR et à l’hydratation
Je lirais volontiers des objections mieux informées sur la question de savoir si React s’est conçu lui-même comme une impasse, et quelles seraient les voies de sortie, mais revenir à PHP n’est pas la réponse
React n’est pas si difficile à apprendre, et ce n’est pas pour rien que même des non-développeurs peuvent en acquérir les bases en quelques semaines de bootcamp
JSX est objectivement supérieur aux systèmes de templates de Django, PHP ou Rails
J’ai l’impression que la moitié des objections lancées à la va-vite viennent de gens qui n’ont même pas benchmarké leurs propres projets avec des outils comme Lighthouse