00:00:00React server components. Pour ou contre ?
00:00:04Ça semble être surtout contre ces temps-ci, mais ça
00:00:08pourrait bien changer avec l'arrivée de TanStack dans la partie.
00:00:13C'est exact, nous avons maintenant des TanStack
00:00:21server components, et ils ont adopté une approche très différente de Next.js.
00:00:26Jetons un œil.
00:00:31Je vais commencer par un paragraphe de leur article d'annonce,
00:00:35qui, je pense, rassurera beaucoup de monde.
00:00:40Il dit : "La plupart des gens conçoivent les React server components
00:00:45d'une manière centrée sur le serveur.
00:00:48Le serveur possède l'arborescence, "useClient" marque les parties interactives,
00:00:52et les conventions du framework déterminent comment tout cela s'assemble.
00:00:57Cela transforme les React server components,
00:01:01d'une primitive utile, en un élément autour duquel toute votre application doit graviter.
00:01:06Nous ne pensons pas que vous devriez devoir adhérer
00:01:10à tout ce modèle dès le départ simplement pour tirer profit des React server components."
00:01:15En substance, ce qu'ils disent, c'est qu'ils ne veulent pas suivre la voie de Next.js
00:01:18où tout est "server component" par défaut, et où vous avez besoin de la directive "useClient"
00:01:22là où vous voulez de l'interactivité.
00:01:27Au lieu de cela, TanStack veut penser les choses ainsi : et si vous pouviez utiliser
00:01:32des React server components de manière aussi granulaire que vous pourriez récupérer du JSON côté client ?
00:01:36Avec cet objectif en tête, examinons
00:01:40la manière dont ils ont réellement implémenté les server components,
00:01:45car, spoiler : j'adore vraiment leur approche.
00:01:49Ce que j'ai ici, c'est une application TanStack Start normale,
00:01:53donc tout, pour le moment, va être un composant client.
00:01:58La seule chose que j'ai faite, ce sont quelques petites étapes d'installation nécessaires
00:02:01pour faire fonctionner les server components, ce qui consiste essentiellement à installer quelques paquets
00:02:06et à modifier votre config Vite.
00:02:10Voici à quoi ressemble la page actuellement ; nous avons notre composant de salutation ici
00:02:14qui, comme vous pouvez le voir, est actuellement un composant client,
00:02:18et dans le code, il s'agit littéralement d'un simple composant React.
00:02:23Ensuite, en bas, nous avons une route TanStack normale, et nous utilisons le composant de salutation.
00:02:27Maintenant, disons que dans notre composant de salutation, vous vouliez effectuer une certaine logique sur le serveur.
00:02:32Dans mon cas, je veux récupérer le nom d'hôte du système d'exploitation,
00:02:36puis aussi certaines variables d'environnement qui ne sont disponibles que sur le serveur,
00:02:41juste pour vous montrer que cela s'exécute réellement là-bas.
00:02:46Pour l'instant, si j'essaie d'utiliser "os.hostname",
00:02:51cela ne fonctionnera pas car c'est une fonction Node, et elle n'est pas disponible dans le navigateur.
00:02:55Ce que nous devons faire, alors, c'est prendre notre composant de salutation et le rendre sur le serveur.
00:02:59La première étape pour faire cela dans TanStack Start est une simple fonction serveur.
00:03:03Comme vous pouvez le voir, j'en ai une ici appelée "getGreeting",
00:03:07et tout ce que nous faisons à l'intérieur, c'est utiliser la nouvelle fonction "renderServerComponent",
00:03:12en plaçant notre composant à l'intérieur, et en retournant le server component rendable
00:03:16que nous obtenons en retour.
00:03:21Vous pouvez voir cela comme une simple création d'une requête GET pour notre composant.
00:03:25Ensuite, tout ce que nous devons faire est simplement de récupérer le composant depuis la fonction serveur que nous avons créée,
00:03:30et nous pouvons le faire à l'intérieur d'un "loader" sur une route ici,
00:03:34donc nous attendons simplement "getGreeting",
00:03:38puis nous retournons cela également, et c'est toujours un server component rendable.
00:03:43Ensuite, nous pouvons l'utiliser à l'intérieur de
00:03:47notre route ici en utilisant "useLoaderData",
00:03:52et nous utilisons simplement le composant en bas comme ceci.
00:03:56Avec cela, nous avons maintenant notre premier TanStack server component.
00:04:01Vous pouvez voir que "os.hostname" fonctionne maintenant, et il récupère également
00:04:05des variables d'environnement qui ne sont disponibles que sur le serveur.
00:04:10Maintenant, ce que j'adore absolument à propos de cette implémentation,
00:04:14c'est que si vous remarquez, la seule nouvelle chose ici est la fonction "renderServerComponent".
00:04:18Le reste était juste du TanStack Start normal.
00:04:22Vous pourriez remplacer cela par de simples données JSON retournées, et vous les récupéreriez exactement de la même manière.
00:04:28Je pense aussi que cette implémentation est vraiment explicite
00:04:32quant à l'endroit où votre code s'exécute réellement.
00:04:37Vous faites tout à l'intérieur d'une fonction serveur, donc c'est assez clair que cela va être exécuté sur le serveur,
00:04:42et aussi à l'intérieur du "renderServerComponent".
00:04:47En fait, je pense que je peux améliorer mon code de démonstration ici en prenant simplement
00:04:51les fonctions que nous exécutons ici en haut, que je veux exécuter sur le serveur, en les mettant
00:04:56à l'intérieur de la fonction serveur,
00:05:00puis en passant simplement ces valeurs dans mon composant de salutation en tant que "props",
00:05:05donc maintenant mon composant de salutation est essentiellement juste un composant nu qui peut être utilisé
00:05:09sur le client ou sur le serveur.
00:05:14J'exécute toute la logique que je veux exécuter sur le serveur à l'intérieur de ma fonction serveur ici.
00:05:18Encore une fois, il est assez explicite que cela va être exécuté sur le serveur.
00:05:22Cela ressemble littéralement à l'exact opposé de la logique utilisée dans Next.js,
00:05:27et je l'adore.
00:05:31Cela signifie que je peux penser à React de manière normale : tout est client d'abord,
00:05:36puis j'ajoute des server components par-dessus quand je le souhaite.
00:05:41Mais que faire si je voulais utiliser un composant client à l'intérieur de mon server component,
00:05:45donc imbriqué dans l'arborescence ?
00:05:49Disons que je voulais ajouter un bouton de compteur ici
00:05:53qui, chaque fois qu'on clique dessus, augmente le compteur.
00:05:57Eh bien, si j'essaie simplement d'ajouter cela dans mon server component ici avec
00:06:01un "onClick" puis aussi un appel à "useState",
00:06:05vous pouvez voir que ça casse complètement.
00:06:10Il dit que "useState" n'est pas une fonction ou que sa valeur de retour n'est pas itérable,
00:06:14et c'est parce que "Greeting" est utilisé comme un server component.
00:06:18Nous ne pouvons pas utiliser cette fonctionnalité client.
00:06:23Pour corriger cela, vous avez deux options, et la deuxième option est certainement la meilleure à utiliser,
00:06:27mais la première option sera familière à ceux d'entre vous qui ont utilisé Next.js.
00:06:32Nous pouvons simplement déplacer cette logique dans son propre composant, puis utiliser la directive "useClient".
00:06:36Cela fonctionne dans les server components de TanStack Start ; nous pouvons simplement utiliser
00:06:40le composant à l'intérieur du server component maintenant, et comme vous pouvez le voir, tout fonctionne bien.
00:06:44L'inconvénient de cette approche, cependant, est que nous avons maintenant un server component
00:06:48contrôlant le rendu d'un composant client,
00:06:53et cela peut commencer à devenir un peu désordonné,
00:06:58c'est-à-dire que si je voulais savoir où se trouvait mon composant de compteur dans l'arborescence,
00:07:03j'irais sur ma route ici et je verrais que nous avons un server component "Greeting",
00:07:08puis je reviendrais dans le server component "Greeting",
00:07:12et à l'intérieur du server component, je verrais que nous avons un composant client,
00:07:17et ce désordre peut vraiment commencer à s'accumuler, et rendre la frontière
00:07:22entre serveur et client un peu floue.
00:07:27TanStack ne se contenterait pas de cela, cependant.
00:07:32Ils se sont demandé : et si le serveur n'avait pas besoin de décider de chaque partie de l'interface
00:07:37qui est destinée au client ?
00:07:42Et cela les a conduits à créer quelque chose d'entièrement nouveau : les composants composites.
00:07:46Pour en utiliser un, la première chose que je vais faire, c'est supprimer notre composant client de notre server component,
00:07:50et je vais simplement le remplacer
00:07:56par n'importe quels enfants de notre composant "Greeting".
00:07:59Ensuite, nous devons aussi changer ce que nous retournons de
00:08:04notre fonction serveur ici.
00:08:08Au lieu de retourner un server component rendable, nous devons retourner
00:08:12ce qu'on appelle une "composite source".
00:08:16Pour ce faire, nous pouvons utiliser notre deuxième fonction d'aide de TanStack server components :
00:08:20"createCompositeComponent".
00:08:24Ici, nous construisons essentiellement un composant
00:08:28où les "props" ici sont considérées comme les emplacements (slots).
00:08:32J'utilise juste un emplacement enfant très simple,
00:08:36donc tout ce que nous mettrons en tant qu'enfant de mon composant composite sera passé
00:08:41dans ce "props.children", que
00:08:45je transmets au composant "Greeting" que nous avions juste avant.
00:08:49Avec cela, encore une fois, ce que nous devons faire, c'est
00:08:53simplement récupérer notre composant composite depuis notre fonction serveur,
00:08:57et nous faisons cela exactement de la même manière dans
00:09:01le "loader" ici.
00:09:06Vous voyez, je renomme simplement "source" en "Greeting",
00:09:10puis je le charge avec "useLoaderData".
00:09:15La seule différence ici, cependant, c'est que nous ne pouvons pas utiliser cela comme un composant.
00:09:19Vous voyez, il génère une erreur ici.
00:09:23Pour rendre réellement un composant composite, nous devons utiliser le composant d'aide
00:09:28"CompositeComponent" que nous obtenons depuis TanStack server components,
00:09:33et en tant que "source prop", nous passons
00:09:38le composant composite que nous récupérons de notre fonction serveur que nous avons créée plus tôt.
00:09:42Avec cela, mon server component est maintenant en train de se rendre comme nous l'avions avant,
00:09:47et je transmets aussi le compteur en tant qu'enfants de ce composant composite,
00:09:51et cela est passé au "Greeting" là où nous
00:09:56l'avions configuré ici, donc il le transmet dans "props.children",
00:10:01donc tout fonctionne maintenant
00:10:05parfaitement bien.
00:10:10Je peux aussi aller dans mon composant compteur et supprimer la directive que nous avions ici,
00:10:14puisqu'elle n'est plus nécessaire car il sait que ce sera un composant client
00:10:18puisqu'il est à l'intérieur d'un composant composite.
00:10:22Ceci est utilisé comme un emplacement.
00:10:26Maintenant, il peut sembler que nous ayons obtenu exactement le même résultat,
00:10:31mais avec plus de travail que juste utiliser la directive "useClient",
00:10:36mais la puissance vient vraiment de l'expérience développeur, et c'est un peu un changement par rapport au modèle "useClient".
00:10:40Au lieu d'avoir notre serveur qui décide où nos composants clients se rendent,
00:10:44comme quand nous avions le composant compteur à l'intérieur du server component lui-même,
00:10:49ce que nous faisons avec les composants composites, c'est dire : "Hé,
00:10:53il va y avoir un emplacement ici, nous allons rendre un composant client,
00:10:58mais le server component lui-même n'a aucune idée de ce que cela va être."
00:11:03Nous ajoutons cela plus tard dans notre code client,
00:11:07donc nous gérons tous les composants basés sur le client à l'intérieur du code client lui-même.
00:11:12Ce n'est que le début, aussi.
00:11:16Si nous jetons un œil à une page plus complexe comme celle-ci, sur les posts, où ce post est rendu côté serveur,
00:11:21il y a deux problèmes que je veux résoudre.
00:11:25Le premier est que je veux ajouter des actions comme
00:11:31aimer le post et suivre l'auteur, mais je veux les ajouter au-dessus du titre ici,
00:11:36et je veux utiliser un composant client.
00:11:41Pour le moment, j'utilise simplement ce modèle d'emplacement "children",
00:11:45ce qui signifie que si je
00:11:49ajoutais mes actions de post ici en bas, elles iraient juste là où sont les commentaires,
00:11:54puisque c'est comme ça que nous avons
00:11:59le composant configuré, donc je veux un moyen de dire à mon server component où mettre des composants clients spécifiques.