<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: David Hockley</title>
    <description>The latest articles on DEV Community by David Hockley (@kodaps).</description>
    <link>https://dev.to/kodaps</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F623806%2Ff0eb49ad-9fb6-40b3-b1c5-5d525900d7b6.jpg</url>
      <title>DEV Community: David Hockley</title>
      <link>https://dev.to/kodaps</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kodaps"/>
    <language>en</language>
    <item>
      <title>4 Reasons Why Coding Brings Me Joy</title>
      <dc:creator>David Hockley</dc:creator>
      <pubDate>Fri, 06 Sep 2024 12:43:31 +0000</pubDate>
      <link>https://dev.to/kodaps/4-reasons-why-coding-brings-me-joy-4ld0</link>
      <guid>https://dev.to/kodaps/4-reasons-why-coding-brings-me-joy-4ld0</guid>
      <description>&lt;p&gt;I started coding when I was 10. My grandfather gave me a ZX81 with 1 kilobyte of RAM. It would plug into the TV, and the clock speed of the CPU was based on the TV's refresh rate.&lt;/p&gt;

&lt;p&gt;And since then, in every single job I've had, I've been coding. Even when coding was not in the job description, even now that I'm in management. At times that was out of &lt;em&gt;necessity&lt;/em&gt;, because the ship was sinking fast and all hands needed to be on deck. (Yes, I've seen my share of startup shipwrecks). But most of the time it is by &lt;em&gt;choice&lt;/em&gt;. Because to me, coding is fun. Here is why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reason 0: Code is a game of exploration, a journey
&lt;/h2&gt;

&lt;p&gt;Coding is all about learning: learning new languages, new technology, new techniques, new ways of doing things. It's about wrapping your head around callbacks, object-oriented programming, asynchronous behavior, promises, functional programming (especially since the arrival of hooks), databases, browsers, mobile platforms, game engines… Obviously, it's not &lt;em&gt;just&lt;/em&gt; about those. But there is a sense where it is a journey into the minds of brilliant (and sometimes not so brilliant) people who have created new, weird, and exciting stuff. And the fun is in the journey, in the process of discovering the ideas and creativity that has gone into producing all this new tech.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reason 1: Code is a construction game
&lt;/h2&gt;

&lt;p&gt;Coding is about creating something out of thin air, electrons, and a sprinkling of imagination. There is a joy in producing something new and beautiful that strangers will experience and hopefully understand and enjoy. Of course, the first iteration usually fails miserably by that standard, but it is also wonderful to then be able to refine and polish something imperfect, to make it into a thing of beauty.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reason 2: Code is a strategy game
&lt;/h2&gt;

&lt;p&gt;There are times when despite your best efforts, the computer refuses to bend to your will, especially when venturing out into unfamiliar territory populated by new technologies and concepts. Or trying to get browsers to behave in a uniform manner. In this situation, it pays to learn how to think laterally, how to come at the problem from a variety of directions, or even to make your way around said problem. There are many ways to skin a cat, to center a div, or to query a database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reason 3: Code is a puzzle game
&lt;/h2&gt;

&lt;p&gt;I love reading whodunnits. I love trying to work out who the culprit is, and unraveling the mystery of the motivations and psychological interactions that underlie it all. And code has a measure of that. In particular when trying to understand the reason why things are not working or, to paraphrase Chesterton, the even darker reason of why things are working when they should not be.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code is my 9 to 5 &amp;amp; my side hustle
&lt;/h2&gt;

&lt;p&gt;All these reasons combine to explain why so many developers choose to spend their leisure time coding: because as Jane McGonigal stated in her book &lt;em&gt;Reality is Broken&lt;/em&gt;: "Games make us happy because they are hard work that we choose for ourselves, and it turns out that almost nothing makes us happier than good, hard work." Coding is good hard work with visible outcomes and a sense of having overcome the perils of the journey when you finally reach your destination.&lt;/p&gt;

&lt;p&gt;And the nature of software means that journey is always beckoning.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Les 4 raisons pourquoi j'adore coder</title>
      <dc:creator>David Hockley</dc:creator>
      <pubDate>Mon, 13 Sep 2021 05:10:33 +0000</pubDate>
      <link>https://dev.to/kodaps/les-4-raisons-pourquoi-j-adore-coder-dog</link>
      <guid>https://dev.to/kodaps/les-4-raisons-pourquoi-j-adore-coder-dog</guid>
      <description>&lt;p&gt;J'ai commencé à coder quand j'avais 10 ans. Mon grand-père m'a donné un ZX81 avec 1 kilo-octet de RAM. Il se branchait sur la télévision, et la vitesse d'horloge de l'unité centrale était calibré sur la fréquence de rafraîchissement de la télévision.&lt;/p&gt;

&lt;p&gt;Et depuis lors, dans chaque emploi que j'ai eu, j'ai codé. Même quand le codage ne faisait pas partie de la description du poste, même maintenant que je suis dans le management. Parfois, c'était par nécessité, parce que le bateau coulait rapidement et que tout le monde devait être sur le pont. (Oui, j'ai vu ma part de naufrages de startups). Mais la plupart du temps, c'est par choix. Parce que pour moi, coder est un plaisir. Voici pourquoi.&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/0IUh0SjmdQ8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Raison 0 : Le code est un jeu d'exploration, un voyage
&lt;/h2&gt;

&lt;p&gt;Coder, c'est avant tout apprendre : apprendre de nouveaux langages, de nouvelles technologies, de nouvelles techniques, de nouvelles façons de faire. Il s'agit de se familiariser avec les callbacks, la programmation orientée objet, le comportement asynchrone, les promesses, la programmation fonctionnelle (surtout depuis l'arrivée des hooks), les bases de données, les navigateurs, les plates-formes mobiles, les moteurs de jeux... Évidemment, il ne s'agit pas &lt;em&gt;que&lt;/em&gt; de cela. Mais il s'agit en quelque sorte d'un &lt;em&gt;voyage&lt;/em&gt;. Un voyage dans l'esprit de personnes brillantes (et parfois moins brillantes) qui ont créé des choses nouvelles, étranges et passionnantes. &lt;/p&gt;

&lt;p&gt;Et le plaisir se trouve dans le voyage, dans le processus de découverte des idées et de la créativité qui ont permis de produire toutes ces nouvelles technologies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Raison 1 : Le code est un jeu de construction
&lt;/h2&gt;

&lt;p&gt;Coder, c'est &lt;em&gt;créer&lt;/em&gt; quelque chose à partir de rien, d'électrons et d'un peu d'imagination. &lt;/p&gt;

&lt;p&gt;Il y a une joie à produire quelque chose de nouveau et de beau que des inconnus vont découvrir et, espérons-le, comprendre et apprécier. Bien sûr, la première itération échoue généralement lamentablement à l'aune de ce critère-là, mais c'est aussi une joie de pouvoir ensuite affiner et polir quelque chose d'imparfait, pour en tirer quelque chose de beau.&lt;/p&gt;

&lt;h2&gt;
  
  
  Raison 2 : Le code est un jeu de stratégie
&lt;/h2&gt;

&lt;p&gt;Il arrive que, malgré tous vos efforts, l'ordinateur refuse de se plier à votre volonté, surtout lorsque vous vous aventurez sur un terrain inconnu peuplé de nouvelles technologies et de nouveaux concepts. &lt;/p&gt;

&lt;p&gt;Ou lorsque vous essayez de faire en sorte que les navigateurs se comportent de manière raisonable ou uniforme. Dans cette situation, il est utile d'apprendre à penser latéralement, à aborder le problème sous différents angles, voire même... à le contourner. Il existe de nombreuses façons d'atteindre son but, de centrer un div ou d'interroger une base de données.&lt;/p&gt;

&lt;h2&gt;
  
  
  Raison 3 : Le code est un jeu de logique
&lt;/h2&gt;

&lt;p&gt;J'adore lire des romans policiers. J'aime essayer de comprendre qui est le coupable, et percer le mystère des motivations et des interactions psychologiques qui sous-tendent tout cela. Et le code a une certaine mesure de cela. &lt;/p&gt;

&lt;p&gt;En particulier lorsqu'il s'agit de comprendre la raison pour laquelle les choses ne fonctionnent pas ou, pour paraphraser Chesterton, la raison encore plus sombre pour laquelle les choses fonctionnent alors qu'elles ne le devraient pas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Le code est mon travail de 9 à 5 et mon activité secondaire.
&lt;/h2&gt;

&lt;p&gt;Toutes ces raisons se combinent pour expliquer pourquoi tant de développeurs choisissent de passer leur temps libre à coder : parce que, comme Jane McGonigal l'a déclaré dans son livre Reality is Broken : "Les jeux nous rendent heureux parce qu'ils représentent un travail difficile que nous choisissons pour nous-mêmes, et il s'avère que presque rien ne nous rend plus heureux qu'un bon et dur labeur". &lt;/p&gt;

&lt;p&gt;Le codage est un bon travail difficile avec des résultats visibles et le sentiment d'avoir surmonté les périls du voyage lorsque vous atteignez enfin votre destination.&lt;/p&gt;

&lt;p&gt;Et la nature du logiciel fait que ce voyage nous appelle à chaque instant.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>6 erreurs de débutant en React, et comment les éviter</title>
      <dc:creator>David Hockley</dc:creator>
      <pubDate>Tue, 07 Sep 2021 07:11:13 +0000</pubDate>
      <link>https://dev.to/kodaps/6-erreurs-de-debutant-en-react-et-comment-les-eviter-edi</link>
      <guid>https://dev.to/kodaps/6-erreurs-de-debutant-en-react-et-comment-les-eviter-edi</guid>
      <description>&lt;p&gt;En tant que manager avec quelques années d'expérience en développement, j'ai souvent des développeurs juniors ou des stagiaires qui viennent me voir pour essayer de comprendre pourquoi leur code ne se comporte pas comme ils s'y attendent. Lorsqu'ils codent en React, cela provient le plus souvent d'un manque de compréhension du comportement de useState. Voici donc cinq erreurs que j'ai vues au cours de l'apprentissage de React et particulièrement de useState.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/gX70XvkGXuw"&gt;
&lt;/iframe&gt;
&lt;br&gt;
 &lt;/p&gt;
&lt;h2&gt;
  
  
  Pas assez d'état
&lt;/h2&gt;

&lt;p&gt;C'est la première erreur commise par un développeur (très) junior qui n'avait pas encore compris à quel moment la  fonction de rendu d'un composant React est appelée. Il avait modifié une variable dans un callback &lt;code&gt;onClick&lt;/code&gt; et s'est ensuite demandé pourquoi cette modification n'était pas prise en compte à l'écran. En règle générale, tout ce qui est externe à l'application doit être stocké quelque part dans l'état (ou dans un mécanisme équivalent), que ce soit le fait qu'un utilisateur ait cliqué ou le retour d'un appel d'API. "Tu devrais stocker cela dans l'état", je lui ai-je dit, "sinon, l'information se perdra entre les trames de rendu". &lt;/p&gt;
&lt;h2&gt;
  
  
  L'état contient trop d'informations
&lt;/h2&gt;

&lt;p&gt;L'erreur suivante (par le même gars) était l'étape d'après, la suite de la précédente, et représentait un mouvement de balancier dans l'autre sens. Il était tellement déterminé à s'assurer que tout était stocké en toute sécurité qu'il a également inclus des valeurs calculées qui étaient simplement le résultat d'autres variables d'état. Bien sûr, s'il s'agissait simplement d'une question de code mal fagotté, il ne serait peut-être pas venu chercher de l'aide. Mais l'affichage ne se mettait à jour qu'une fois sur deux lorsqu'il cliquait. En regardant le code, j'ai vu qu'il faisait quelque chose comme ceci :&lt;br&gt;
&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;setScore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;setButtonActive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Dans le code ci-dessus, le score n'a pas changé entre les deux lignes (parce que nous sommes dans la même trame de rendu - ou "frame"). Et la deuxième ligne stocke quelque chose qui peut être déduit de l'autre variable d'état. Et c'est pour ça que l'affichage ne se mettait pas mis à jour. "Je lui ai dit : "Tu n'as pas besoin de tout stocker, la logique que tu peux déduire des autres variables d'état n'a pas besoin d'être stockée".&lt;/p&gt;
&lt;h2&gt;
  
  
  L'état est mis à jour trop souvent
&lt;/h2&gt;

&lt;p&gt;A un autre endroit du code, le même gars avait écrit quelque chose qui ressemblait à ceci:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;setScore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ..... quelques lignes plus loin &lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;condition2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;setScore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ici de la même façon, le score n'a pas été changé entre les deux lignes, et ne s'incrémente au final qu'une seule fois, au mieux. &lt;/p&gt;

&lt;p&gt;Pour corriger ceci, on peut passer une fonction à la fonction d'état&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;setScore&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ..... quelques lignes plus loin &lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;condition2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;setScore&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ainsi la mise à jour de l'état s'applique sur la valeur en cours de l'état, et non sur la valeur initialement définie en début de l'appel de la fonction de rendu.&lt;br&gt;
 &lt;br&gt;
Il n'en était pas encore là dans son apprentissage, mais un jour il apprendra que si l'état est un peu complexe, avec des variables interdépendantes qui doivent être mises à jour de manière coordonnée ou non triviale, il pourrait être préférable de faire appel à useReducer. Mais il n'en est pas là. Pas encore.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;
  
  
  Redéfinir trop de choses dans le rendu
&lt;/h2&gt;

&lt;p&gt;Quelques jours plus tard, il était de retour. Il avait un formulaire où il était convaincu de tout faire correctement, et pourtant l'état était réinitialisé chaque fois qu'il entrait des données dans le formulaire HTML. Maintenant, à ce stade, je tiens à préciser qu'il s'agit d'une personne à la fois très brillante et très sympathique. Cependant, il venait de commencer à apprendre React, donc il faisait à peu près toutes les erreurs à faire, et je commençais à douter de la sagesse de lui faire développer en utilisant React. Mais c'était un stage, et il était venu pour apprendre. Et l'expérience n'est souvent que la somme des erreurs passées, donc selon cette norme... tout se passait très bien. &lt;br&gt;
Il avait pris à cœur mes conseils sur le fait de recalculer des choses qui n'avaient pas besoin d'être stockées. Mais il avait été un peu trop enthousiaste à propos de tout cela. La conversation s'est déroulée comme suit :&lt;/p&gt;

&lt;p&gt; - Attendez, où se termine ce composant ? &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Juste en haut du fichier, ici. &lt;/li&gt;
&lt;li&gt;Et où est-ce qu'il se termine ? Je ne peux pas trouver la fin.  
 - C'est ici, en bas du fichier. 
 - Et c'est quoi tout ça au milieu ? 
 - Ce sont les fonctions et les constantes que j'ai définies, et le composant pour le formulaire HTML. Parce que j'ai besoin que l'état de ce composant soit partagé avec le composant principal.
 
J'espère qu'il n'a pas vu le regard de désespoir qui a du paraître sur mon visage. 
"Toutes les constantes et toutes les fonctions qui fournissent simplement une logique sans manipuler l'état peuvent être déplacées hors du composant, dans un fichier séparé. Vous pouvez juste importer vos points d'entrée et les utiliser." Je lui ai dit. "Et le composant Form redéfini dans le composant principal... eh bien vous le redéfinissez complètement à chaque trame de rendu, donc vous montrez en fait un nouveau composant à chaque mise à jour."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nous avons finalement refactoré entièrement ce bout de code.&lt;/p&gt;
&lt;h2&gt;
  
  
  S'appuyer uniquement sur les props initiaux pour définir l'état
&lt;/h2&gt;

&lt;p&gt;Je dois avouer que je me suis personnellement rendu coupable de cette erreur. J'avais créé un composant qui affichait essentiellement une barre de progression circulaire basée sur les props que je lui transmettais. Il stockait donc son état comme ceci :&lt;br&gt;
&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setProgress&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Bien sûr, le problème ici est que tout changement dans les props n'affectera pas l'état, une fois que la première initialisation est faite. &lt;br&gt;
Ici, il y a deux solutions possibles, qui dépendent de ce qui est fait exactement dans le composant. Si le composant n'a pas de logique interne qui met à jour l'état, vous n'avez pas besoin de stocker l'état. Mais dans mon cas spécifique, j'avais besoin de l'état, donc j'ai utilisé useEffect :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setProgress&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="nf"&gt;setProgress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Mise à jour de l'état avec un objet muté
&lt;/h2&gt;

&lt;p&gt;Il s'agit d'une erreur classique qui découle d'un manque de compréhension du fonctionnement des objets en JavaScript, et plus précisément du fait que la mutation des objets ne déclenche pas la détection des changements de React. En effet, l'affectation d'un objet se fait par référence, c'est-à-dire que lorsque vous affectez un objet à une variable, vous ne faites que stocker le pointeur de l'objet dans votre variable, de sorte que deux variables peuvent pointer vers le même objet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;nom&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ici a==b et a.name == "Alice" ;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En termes de React, cela signifie que faire quelque chose comme ceci ne mettra pas à jour l'affichage, car la valeur de la variable state ne change pas, elle pointe toujours vers le même objet :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [state, setState]=useState({score:0}) ;
const onClick =() =&amp;gt; {
  state.score += 1 ;
  setState(state) ;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La solution, bien sûr, est de créer une copie de l'état, par exemple avec l'opérateur d'étalement ou en déclarant un nouvel objet (ou, pour être parfaitement honnête, en utilisant simplement un scalaire dans l'exemple ci-dessus) :&lt;br&gt;
&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({..&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;score&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pas juger
&lt;/h2&gt;

&lt;p&gt;Même si le chemin était tortueux, mon collègue s'est plu à apprenant à manipuler React. Et je suis certain que j'ai du faire au moins autant d'erreurs dans processus d'apprentissage, je suis parfois horrifié quand je vois du vieux code à moi. &lt;br&gt;
Et pour être parfaitement honnête, j'ai moi-même beaucoup profité des interactions. Le fait d'expliquer comment les choses marchent est une bonne façon de continuer à apprendre, et une expérience gratifiante.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>React vs Angular : lequel choisir ?</title>
      <dc:creator>David Hockley</dc:creator>
      <pubDate>Sun, 22 Aug 2021 07:09:03 +0000</pubDate>
      <link>https://dev.to/kodaps/react-vs-angular-lequel-choisir-42nk</link>
      <guid>https://dev.to/kodaps/react-vs-angular-lequel-choisir-42nk</guid>
      <description>&lt;p&gt;Angular ou React.js : Lequel est-il préférable d'apprendre ? Laquelle est la meilleure à utiliser pour un projet ? Et surtout, quelles sont les différences structurelles et fondamentales entre ces deux solutions ?&lt;br&gt;
Je travaille avec Angular depuis 2016 et avec React depuis 2019 (et par Angular, j'entends Angular 2 et plus, pas AngularJs). Et pour moi, bien que les deux servent un objectif similaire, ils se sentent radicalement différents à coder avec.&lt;/p&gt;

&lt;p&gt;Le premier point à souligner est qu'Angular est utilisé sur Gmail et sur les produits Google en général, sur Microsoft Office Online, sur UpWork, sur Sony et sur Forbes. Alors que React est utilisé chez Facebook, Instagram, Netflix, Dropbox et Uber. Donc Angular et React sont tous deux des solutions matures avec de solides références. Cependant, ces noms racontent l'histoire de deux mondes très différents et donnent un premier indice sur la différence sous-jacente entre les deux solutions.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ics7WsBW-6g"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  Une différence de philosophie incarnée visuellement
&lt;/h1&gt;

&lt;p&gt;Les logos racontent une histoire similaire. Le logo d'Angular est un bouclier, symbole de solidité et de sécurité. En revanche, le logo de React est un atome. Si vous combinez la sémantique de React et un atome, vous obtenez une explosion, une réaction atomique. Le contraire de la sécurité.&lt;br&gt;
Les énoncés de mission internes de ces deux entreprises montrent la même opposition. Google, où Angular a été créé, vise à "Ne pas faire de mal". Facebook, berceau de React, veut "Move fast and break things". Alors que Google semble très respectueux de la loi, la devise interne de Facebook dégage une atmosphère rebelle de mauvais garçon. Leurs deux solutions (Angular et React) incarnent ces deux mentalités. Et les entreprises qui utilisent ces deux solutions reflètent cet état d'esprit : les entreprises solides et sensées sont vantées du côté d'Angular tandis que les champions de React sont disruptifs. Si vous deviez traduire cela en termes de jeu de rôle, Angular aurait un alignement Lawful Good et React un alignement Chaotic Neutral.&lt;/p&gt;

&lt;h1&gt;
  
  
  Quelle structure ?
&lt;/h1&gt;

&lt;p&gt;En termes de structure interne, la même opposition s'applique : il n'y a pas de structure préimposée du côté de React. Dans Angular, il existe une convention de codage et de nommage dérivée du modèle MVC (model view controller). La structure du système de fichiers reflète cela, chaque module a un dossier, dans les dossiers des modules, on a des dossiers pour chaque composant. Et tout cela doit être respecté pour que l'application compile.&lt;br&gt;
React n'a pas de structure MVC, juste des fonctions qui rendent le code directement (du moins si nous utilisons des composants fonctionnels). La manière de structurer le code et le système de fichiers est laissée fermement à la discrétion du développeur.&lt;/p&gt;

&lt;h1&gt;
  
  
  L'impact pratique
&lt;/h1&gt;

&lt;p&gt;En quoi Angular et React sont-ils différents en pratique ? D'après mon expérience, les différences de structure conduisent à des composants plus gros et de plus grande portée dans Angular, alors que React est propice à des composants plus ciblés. La réutilisation des composants est également plus complexe dans Angular, alors que le faire dans React demande un effort minimal.&lt;br&gt;
Angular étant un framework à part entière avec un champ d'application plus large (il fournit plus de fonctionnalités d'emblée, comme le routage, l'internationalisation ou la gestion bidirectionnelle de l'état) et une structure prédéfinie, sa courbe d'apprentissage est plus raide.&lt;br&gt;
React, en revanche, est une bibliothèque ciblée, avec moins de structure et moins de portée, ce qui facilite l'apprentissage car il y a moins de choses à apprendre, du moins au début. Vous pouvez couvrir les principaux concepts en un après-midi. Cette focalisation unique est également ce qui lui confère une plus grande flexibilité.&lt;br&gt;
Angular offre sécurité et structure, alors que React offre agilité et rapidité.&lt;/p&gt;

&lt;h1&gt;
  
  
  En conclusion : Lequel dois-je recommander ?
&lt;/h1&gt;

&lt;p&gt;Pour commencer, je recommande d'apprendre JavaScript et Typescript avant d'apprendre l'un ou l'autre. Une fois que c'est fait, si vous le pouvez, apprenez les deux. Si ce n'est pas le cas, ma recommandation dépendrait de vos traits de personnalité, de votre aversion au risque et du degré de structure dont vous avez besoin. Si vous avez besoin que les choses soient standardisées et sécurisées, je conseillerais Angular. Si vous avez besoin d'action et de flexibilité, je recommanderais React. Si vous souhaitez une carrière de développeur dans le secteur bancaire ou un environnement de travail stable, privilégiez Angular. Si vous préférez travailler plutôt dans une start-up où tout bouge dans tous les sens, je recommande React. Les deux sont de bons choix, mais vous seul pouvez répondre à celui qui correspond le mieux à l'endroit où vous voulez aller.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>A la découverte de Nuxt : que vaut Nuxt vs Next ?</title>
      <dc:creator>David Hockley</dc:creator>
      <pubDate>Sun, 22 Aug 2021 06:55:44 +0000</pubDate>
      <link>https://dev.to/kodaps/a-la-decouverte-de-nuxt-que-vaut-nuxt-vs-next-1el1</link>
      <guid>https://dev.to/kodaps/a-la-decouverte-de-nuxt-que-vaut-nuxt-vs-next-1el1</guid>
      <description>&lt;p&gt;Je me suis donné comme objectif en début d'année d'essayer de voir comment marche Vue. Comme vous le savez peut-être, je suis un fan de NextJS, et dès mes premières recherches sur Vue j'ai vu qu'il y avait un équivalent de NextJS chez Vue, qui s'appelle Nuxt. C'est ce que j'appelle des "méta-framework" (et surement pas que moi d'ailleurs) puisque ce sont des framework qui se construisent par dessus d'autres framework. Je me suis dit qu'un bon point cas d'usage pour apprendre ces méta-framework serait d'essayer de faire un blog. J'ai conscience de 3 méta frameworks principaux, à savoir : NextJS, NuxtJS et Sveltekit, qui est la version dans Svelte. Cependant Sveltekit est encore trop jeune pour que je puisse le recommander même si il a l'air très intéressant, donc on va laisser Sveltekit pour plus tard. &lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/H69voPpZ_WU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Aujourd'hui nous allons donc nous poser deux questions :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Qu'est-ce que Nuxt&lt;/strong&gt;, qu'est-ce qu'apportent les framework fullstack comme Nuxt et Next ? Quels sont les points communs entre Nuxt et Next ?&lt;/li&gt;
&lt;li&gt;Que &lt;strong&gt;vaut Nuxt&lt;/strong&gt;, comparé à NextJS, notamment en termes de "DX", d'expérience dévelopeur. Quels sont les différences entre Nuxt et Next ?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Qu'est-ce que Nuxt ? (les points communs)
&lt;/h2&gt;

&lt;p&gt;Nuxt est l'équivalent de Next, dans le monde de Vue. Une fois qu'on a dit ça, on à à la fois rien dit et tout dit. &lt;/p&gt;

&lt;p&gt;Comme vous le savez peut-être, le principal intérêt des frameworks de type Vue ou React c'est qu'ils permettent d'implémenter côté client une partie de la &lt;strong&gt;logique et de la navigation traditionnellement été réalisés côté serveur&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Ca a pour avantage de permettre une &lt;strong&gt;ergonomie plus fluide&lt;/strong&gt;, mais ça a pour inconvénient que ça demande du coup un effort au navigateur pour interpréter le contenu qu'on lui envoie, puisqu'il faut télécharger et interpréter le Javascript en plus d'afficher le HTML qu'on lui fournir. En termes d'optimisation pour les moteurs de recherche, un React "de base" marche moins bien que des technologies côté serveur. &lt;/p&gt;

&lt;p&gt;La solution qu'implémentent Nuxt et Next (et je crois, Sveltekit) consiste à faire du &lt;strong&gt;rendu JavaScript côté serveur&lt;/strong&gt; (ou SSR: server-side rendering), pour faciliter la tache au "crawler" de Google. En plus de lui cela, ce système permet aussi de gérer et générer les méta-datas pour chaque page (le title, la meta-description etc.) ce qui permet &lt;/p&gt;

&lt;p&gt;Cette solution permet aussi, dans le cas où il n'y a pas de données dynamiques, à faire des rendus de page statiques, c'est à dire qui peuvent être hébergés sur une solution de type S3 qui se contente juste d'envoyer des fichiers sans avoir de code qui tourne. &lt;/p&gt;

&lt;p&gt;Les framework fullstack comme Next comme Nuxt fonctionnent en deux phases. Dans première phase, le serveur génère une première version de la page qui contient toute la structure HTML de la page, ainsi que du code javascript qui permet de la rendre interactive après coup, après qu'elle soit affichée. &lt;/p&gt;

&lt;p&gt;Ainsi on a une page qui s'affiche rapidement mais qui devient interactive par la suite. Ce fonctionnement optimise donc à la fois le référencement et l'expérience utilisateur, et permet d'avoir des méta-datas optimisés pour les moteurs de recherche. De plus, il permet de créer des fichiers statiques qui permettent d'avoir des coûts d'hébergement qui sont plus faibles, et tout un tas de choses comme ça qui sont appréciables comme l'AMP, ce genre de choses. Et c'est pour ça qu'existent ces framework fullstack. A mon sens, ils représentent l'avenir du développement, notamment en raison de l'amélioration qu'ils apportent à l'expérience développeur:  les changements apparaissent tout de suite à l'écran, sans avoir besoin de rafraîchir manuellement. &lt;/p&gt;

&lt;h2&gt;
  
  
  Quelles sont les particularités de Nuxt en termes de DX ?
&lt;/h2&gt;

&lt;p&gt;Pour comparer ces deux frameworks j'ai choisi un angle un peu particulier, un cas pratique : le développement d'un blog. Comment est-ce qu'on peut comparer Next et Nuxt sous l'angle de l'expérience développeur. J'ai comparé les deux solutions sur trois étapes du développement. 1. Premièrement, l'installation : que se passe-t-il quand on installe, quel est l'expérience de l'installation ? 2. Deuxièmement, la création de la page index, et la récupération du contenu. 3. Troisièmement, la création d'une page d'u article&lt;/p&gt;

&lt;h3&gt;
  
  
  L'installation
&lt;/h3&gt;

&lt;p&gt;A l'installation, Nuxt propose plus d'options. Avec Next, il y a besoin d'installer les pièces supplémentaires par la suite, là où Nuxt propose directement d'installer Typescript, ou des frameworks CSS comme Bootstrap, Bulma, Tailwind et d'autres encore. De la même façon, Nuxt prend en charge l'installation de mécanismes de test (et propose différentes solutions) ou de lint. &lt;br&gt;
Nuxt me tient par la main : tout est déjà préparé. Il n'y a pas besoin de fouiller sur internet pour trouver des informations de pertinence et de fraicheur douteuses, et qui proposent des manipulations fastidieuses. De ce fait, l'expérience développeur est meilleure à l'installation sur Nuxt. &lt;/p&gt;

&lt;h3&gt;
  
  
  La recherche de contenu (création de la page index)
&lt;/h3&gt;

&lt;p&gt;Nuxt dispose d'un accesseur particulier ($content) qui permet de gérer directement le contenu, et ce grâce à une syntaxe ostensiblement de celle de MongoDB. La librairie permet de chercher directement du contenu avec des filtres, des tris, ou en sélectionnant qui sont juste après ou juste avant. Tout cela rend la gestion du contenu beaucoup plus facile et que ce que nous avons dans Next, où il faut coder l'accès au contenu soi-même. Sur ce point la Nuxt est devant. &lt;/p&gt;

&lt;h3&gt;
  
  
  Création d'une page d'un article
&lt;/h3&gt;

&lt;p&gt;Comme le fait Next, le routage (l'association d'une url et d'un contenu) se fait en fonction des noms de fichiers sur le disque dur. La mise en page se fait de manière très similaire dans les deux solution. Deux choses particulières sont à souligner. Première chose: Nuxt s'installe un testeur Tailwind qui permet de voir directement quels sont les styles qui ont été activés par la configuration sur cette page. C'est très agréable de ne pas avoir à combiner mentalement la documentation de tailwind et les modifications spécifiques dans le fichier de configuration : On a directement le résultat dans un testeur. La deuxième différence sympathique : Nuxt propose un éditeur intégré pour modifier à la volée le contenu texte. Nul besoin d'aller chercher dans le code source, l'opération est directe et facile. Ici aussi Nuxt propose une meilleure expérience développeur&lt;/p&gt;

&lt;h2&gt;
  
  
  Les à côtés
&lt;/h2&gt;

&lt;p&gt;De manière générale la documentation de Nuxt est très bien faite et propose beaucoup d'exemples. Il y a notamment l'exemple de comment utiliser Typography de Tailwind, un plugin de Tailwind qui permet de faire une mise en page d'article de blog déjà bien configurée. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions... que choisir ?
&lt;/h2&gt;

&lt;p&gt;Sur les trois points, Nuxt a été devant. Si je partais de zéro, si je maitrisais autant Vue que React, je choisirai Nuxt. Seulement ce n'est pas le cas, je suis déjà bien familier avec Next et React, et je ne maitrise pas Vue (qui ressemble trop à Angular pour attiser mon appétit d'apprentissage). J'espère juste que Nuxt va inspirer les développeurs de Next, que les deux solutions vont s'inspirer mutuellement. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Défi Framework SSR : A la découverte de Svelte &amp; Vue et de leurs frameworks SSR</title>
      <dc:creator>David Hockley</dc:creator>
      <pubDate>Sat, 15 May 2021 03:42:49 +0000</pubDate>
      <link>https://dev.to/kodaps/defi-framework-ssr-a-la-decouverte-de-svelte-vue-et-de-leurs-frameworks-ssr-3bhg</link>
      <guid>https://dev.to/kodaps/defi-framework-ssr-a-la-decouverte-de-svelte-vue-et-de-leurs-frameworks-ssr-3bhg</guid>
      <description>&lt;h1&gt;
  
  
  Pourquoi ce défi ?
&lt;/h1&gt;

&lt;p&gt;J'adore le principe de &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;NextJS&lt;/a&gt;. C'est efficace, l'expérience développeur est très fluide et agréable. La documentation est très bonne. Il y a une bonne communauté. C'est basé sur React qui mène la barque en termes de framework javascript. &lt;/p&gt;

&lt;p&gt;Mais j'ai eu plusieurs question de l'ordre de "maintenant que Vue 3 est sorti, est-ce que React risque pas de se faire damer le pion ?" ou "Est-ce que Svelte ce ne serait pas mieux que React ?". Pour chacun de ces frameworks il y a un équivalent de Next : Vue a Nuxt, et Svelte vient de sortir la beta publique de Sveltekit. Et ça se trouve ce sont des solutions plus efficaces &amp;amp; agréables ? Est-ce qu'un jour l'un d'eux va remplacer NextJS dans mon petit coeur ? Qui sait ? &lt;/p&gt;

&lt;p&gt;Mais le découvrir demande un temps d'investissement &amp;amp; d'apprentissage, et j'avais pas tellement de projet à mettre en face, parce que j'aime bien apprendre en faisant. Donc j'ai besoin d'avoir un but précis. &lt;/p&gt;

&lt;p&gt;Et là je me suis dit : "Et si je faisais un blog francophone ?" J'ai déjà un blog sur Medium, qui a une bonne ergnomie d'écriture, mais qui n'est pas tellement adapté pour un public francophone. NextJS serait un très bon choix technologique pour ce cas d'usage (et j'explique comment faire ici), mais je vois là aussi l'occasion d'apprendre d'autres frameworks, et les tester sur un cas précis. Du coup je me suis donné un défi de créer un blog en Nuxt/Vue et en Sveltekit/Svelte.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pourquoi un blog ?&lt;/strong&gt; Pour plusieurs raisons : c'est un cas d'usage "de la vraie vie", qui est à la fois concrêt et tout de même relativement simple (plus simple en tout cas qu'un jeu vidéo ou qu'un site de vente en ligne). Précisons tout de meme tout de suite que je n'ai aucune idée si je vais maintenir le blog en question une fois mon choix fait, c'est un autre débat :D&lt;/p&gt;

&lt;h1&gt;
  
  
  Comment choisir ?
&lt;/h1&gt;

&lt;p&gt;Dans un blog avec un framework de type NextJS, je voudrais pouvoir :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;avoir du &lt;strong&gt;contenu dynamique&lt;/strong&gt; : écrire des articles en markdown, les lister automatiquement dans une page index et les injecter dans une page blog générique&lt;/li&gt;
&lt;li&gt;générer des &lt;strong&gt;pages statique, et les héberger sur S3&lt;/strong&gt;, et s'il y a besoin de logique serveur fonctionner en serverless&lt;/li&gt;
&lt;li&gt;utiliser &lt;a href="https://tailwindcss.com" rel="noopener noreferrer"&gt;Tailwind&lt;/a&gt;, qui est mon framework CSS préféré en ce moment&lt;/li&gt;
&lt;li&gt;inclure des videos YouTube &lt;/li&gt;
&lt;li&gt;afficher du code, évidemment, il faut pouvoir faire un...
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Idéalement j'aimerais pouvoir en profiter pour mieux comprendre un framework que je ne connais pas encore. A première vue j'ai deux choix, qui sont des équivalents de Next: &lt;em&gt;Nuxt.JS&lt;/em&gt;, sur la base de Vue 3, ou &lt;em&gt;Sveltekit&lt;/em&gt;, sur la base de Svelte.&lt;/p&gt;

&lt;p&gt;J'ai donc suivi les guides de démarrage de ces deux framework pour (éventuellement) en choisir un. &lt;/p&gt;

&lt;p&gt;Avec bien sur l'option de rester sur NextJS si aucun des deux ne me convainc, évidemment !&lt;/p&gt;

&lt;p&gt;Mes critères de choix prendront principalement en compte :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;la facilité d'apprentissage et d'arriver à mes fins&lt;/li&gt;
&lt;li&gt;la documentation&lt;/li&gt;
&lt;li&gt;le "DX", c'est-à-dire l'expérience développeur&lt;/li&gt;
&lt;li&gt;l'originalité et la logique du framework&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Du peu que j'en ai lu, Vue a été crée par un certain Evan You qui avait travaillé sur Angular JS. Même si Angular 2+ n'a pas grand chose à voir avec Angular JS, j'ai l'impression à première vue que Svelte utilise des concepts complètement différents de ce que je connais déjà (à savoir React et Angular, côté framework côté client), donc je vais commencer avec Svelte et Sveltekit &lt;/p&gt;

&lt;p&gt;(Ah oui, petit détail, au cas où ce ne serait pas évident : j'utilise cet article - pendant que je suis en train de l'écrire en Markdown - comme contenu initial pour tester les trois systèmes de blog).&lt;/p&gt;

&lt;p&gt;Du coup dans l'ordre nous allons voir :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Comment &lt;a href="https://dev.to/gosev/tutorial-next-js-tailwind-creer-un-blog-4la5"&gt;mettre en place un blog sous NextJS&lt;/a&gt; et, en prime comment faire en NextJS un &lt;a href="https://dev.to/gosev/effet-zoom-de-medium-en-css-avec-nextjs-8j5"&gt;effet de zoom &amp;amp; déblur sur l'image&lt;/a&gt; principale comme ce que fait Medium.&lt;/li&gt;
&lt;li&gt;Ce qu'est &lt;a href="https://dev.to/gosev/defi-framework-ssr-1-a-la-decouverte-de-svelte-sveltekit-17aa"&gt;Svelte&lt;/a&gt; et comment ça marche&lt;/li&gt;
&lt;li&gt;Comment (je m'en sors quand j'essaie de) créer un blog avec Sveltekit &amp;amp; Tailwind&lt;/li&gt;
&lt;li&gt;Ce que sont Vue &amp;amp; Nuxt, et comment ils marchent&lt;/li&gt;
&lt;li&gt;Comment on peut créer un blog avec Nuxt &amp;amp; Tailwind&lt;/li&gt;
&lt;li&gt;Ce qu'on peut dire des points communs et des différences entre Sveltekit, Nuxt et Next pour en tirer nos conclusions &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Su ce c'est parti pour la première partie, comment &lt;a href="https://dev.to/gosev/tutorial-next-js-tailwind-creer-un-blog-4la5"&gt;mettre en place un blog sous NextJS&lt;/a&gt;&lt;/p&gt;

</description>
      <category>french</category>
      <category>ssr</category>
      <category>svelte</category>
      <category>vue</category>
    </item>
    <item>
      <title>C'est quoi Svelte ? Pourquoi cet étonnant framework mérite d'être connu</title>
      <dc:creator>David Hockley</dc:creator>
      <pubDate>Sat, 15 May 2021 03:42:22 +0000</pubDate>
      <link>https://dev.to/kodaps/c-est-quoi-svelte-pourquoi-cet-etonnant-framework-merite-d-etre-connu-p4m</link>
      <guid>https://dev.to/kodaps/c-est-quoi-svelte-pourquoi-cet-etonnant-framework-merite-d-etre-connu-p4m</guid>
      <description>&lt;p&gt;Je me suis &lt;a href="https://dev.to/gosev/defi-framework-ssr-next-vs-vs-nuxt-vs-sveltekit-454d"&gt;lancé un défi&lt;/a&gt; de créer un blog avec trois frameworks : Svelte/Sveltekit, Vue/Nuxt et React/Next, pour me donner un cas pratique et donc un angle d'attaque pour apprendre les frameworks. &lt;br&gt;
J'ai commencé par Svelte. Pourquoi celui-là ? Du peu que j'en ai lu, Vue a été crée par Evan You qui avait travaillé sur Angular JS. Même si Angular 2+ n'a rien à voir avec Angular JS, j'ai tout de meme l'impression à première vue que Svelte utilise des concepts complètement différents de ce que je connais déjà (à savoir React et Angular, côté framework côté client), et du coup ça m'intéresse de les apprendre, de les comprendre, et avec un peu de chance de vous aider à les comprendre aussi. &lt;/p&gt;

&lt;p&gt;Ma technique pour apprendre c'est de faire, donc souvent je lance, j'installe, j'essaie de regarder les exemples, de bidouiller et de comprendre, et si vraiment je galère, le lis les docs. Du coup j'ai installé Svelte (et Sveltekit), avec des exemples de base, j'ai bidouillé et...ce fut un echec cuisant. Je comprenais pas comment marchait l'état, comment il se mettait à jour. Du coup, je me suis plongé dans la documentation et le tutorial, et j'ai essayé de comprendre ce qu'est Svelte. &lt;br&gt;
&lt;em&gt;(pour ceux qui préfèrent, voici la version vidéo de cet article)&lt;/em&gt;&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/5W5i5KhIeaQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  C'est quoi Svelte ?
&lt;/h1&gt;

&lt;p&gt;D'après la documentation, Svelte n'utilise mais de DOM virtuel, mais est un "framework UI qui compile les composants pour en faire du Javascript basique". Contrairement à React ou Vue qui embarquent le framework dans la page. Qu'est-ce que ça veut dire ?&lt;/p&gt;

&lt;p&gt;J'ai mis du temps à comprendre ce que ça voulait dire, et à comprendre quels principes soustendent le framework. Il n'y a pas dans Svelte de setState explicite, pas d'endroit où on signale que "ceci est un état", seulement un :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Et je me disais que quelque part dans ma page ça allait donc donner lieu à un "let counter = 1" quelque part dans la page en sortie. Mais là réalité est bien plus étrange et plus intéressante.  &lt;/p&gt;

&lt;p&gt;A un moment en lisant les documents et les vidéos, j'ai eu un "Aha moment", un moment d'illumination. Pourtant tout était effectivement dit dans la phrase "Svelte compile les composants". En réalité, Svelte n'est &lt;strong&gt;PAS un framework&lt;/strong&gt;. En tout cas pas en premier lieu, et pas au sens où on l'entend avec React ou Vue. &lt;/p&gt;

&lt;p&gt;Avant tout, Svelte est un &lt;strong&gt;compilateur&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Et ce compilateur &lt;em&gt;triche&lt;/em&gt;. Alors certes de manière très intelligente. Mais il donne l'impression qu'on code du javascript, et ce n’est pas tout à fait vrai. &lt;/p&gt;

&lt;p&gt;Svelte triche en &lt;strong&gt;surchargeant l'opérateur =&lt;/strong&gt;, en lui rajoutant un effet de bord. C'est à dire qu'il en fait une fonction, qui met à jour tous les endroits où la variable est utilisée. Puisque de la même façon, Svelte repère en avance dans le HTML, au moment du build, là ou il y a des dépendances envers cette variable. &lt;/p&gt;

&lt;p&gt;Et c'est là que devient intéressant le fait qu'il n'y ait pas de DOM virtuel. React garde en mémoire l’arbre des composant et toutes les variables d’état et les paramètres, et leurs valeurs. A l'étape t, tel composant avait telle classes, et tel style, et telles valeurs, et à l'étape t + 1, il a toujours tel classes, et telles valeurs, mais le style a changé, donc on recalcule les composants qui en dépendent. Chaque itération il faut comparer un à un tous les éléments de l'arbre des composants. ET ça c'est couteux. &lt;/p&gt;

&lt;p&gt;Svelte, à l'inverse, cable directement la variable sur le HTML, avec une fonction, en surchargeant l'opérateur d'affectation =.   &lt;/p&gt;

&lt;p&gt;Et Svelte va plus loin, en surchargeant aussi la notion de label, qui est du &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label" rel="noopener noreferrer"&gt;Javascript valable mais un peu exotique&lt;/a&gt;, pour créer la notion de &lt;strong&gt;dépendance entre variables&lt;/strong&gt;. Le nom du label fait référence à la notion d'Observable : $.  Voyons un exemple :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt;
  &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="nx"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt; {greeting}!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ici, le code sort &lt;strong&gt;Hello Bob!&lt;/strong&gt;, alors que la ligne avec le $ a lieu avant l'affectation de "Bob" à la variable firstName. Comme si le lien entre greeting et firstName n'était pas juste une relation éphémère mais un lien durable. Un mariage au lieu d'un plan Q, en somme.   &lt;/p&gt;

&lt;p&gt;Si on loggue ce qui se passe, on y voit plus clair. Avec un log placé à cet endroit :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt;
  &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="nx"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt; {greeting}!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On a juste un "undefined" dans la console - le code dans le $ n'a pas encore été appelé, apparemment. Mais ce qui est intéressant avec cette notation c'est qu'il est possible d'y mettre un bloc de code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt;
  &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
   &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt; {greeting}!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Et dans ce cas on dans la console "undefined", puis "Hello Bob". Ca parait logique. &lt;/p&gt;

&lt;p&gt;Mais ce qui est intéressant c'est qu'on peut mettre &lt;em&gt;plusieurs&lt;/em&gt; $. Et si on s'amuse à les mettre dans le désordre, avec le console.log &lt;em&gt;avant&lt;/em&gt; l'affectation à la nouvelle valeur, que se passe-t-il ?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt;
  &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
   &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; 
  &lt;span class="nx"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ici, on pourrait s'attendre (merci React avec l'ordre des hooks) à ce que les $ soient exécutés dans l'ordre où ils sont déclarés. &lt;/p&gt;

&lt;p&gt;Et bien non, pas du tout. Dans la console on voit les logs 3 (avec "undefined"), puis 2 puis 1. Et en réalité Svelte a détecté une sorte de graphe de dépendances. Le block où il y a le log 2 a une dépendance sur firstName, et met à jour la variable greeting. Le blog 3 a une dépendance sur la variable greeting, et est donc exécuté après, une fois que greeting est changé. &lt;/p&gt;

&lt;p&gt;Bon et évidemment comme j'ai l'esprit tordu j'ai tout de suite essayé de faire une dépendance cyclique:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hum&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;$&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="nx"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mais le compilateur l'a détecté et a sorti une erreur, donc tout va bien :D&lt;/p&gt;

&lt;p&gt;Pour info, si vous voulez écouter un gars qui explique ça bien mieux que moi, mais en Anglais, voici le créateur de Svelte qui explique les concepts sous jascents que je viens d'exposer : &lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/AdNJ3fydeao"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Voyons à présent plus en détail le fonctionnement de Svelte, voici quelque points saillants que j'ai notés. Je ne peux évidemment pas expliquer &lt;em&gt;in extenso&lt;/em&gt; comment coder en Svelte, mais juste sousligner quelques éléments marquants. &lt;/p&gt;

&lt;h1&gt;
  
  
  Comment coder avec Svelte, premier pas
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Les composants
&lt;/h2&gt;

&lt;p&gt;Les composants sont dans des fichiers .svelte, et ressemblent à une page HTML, avec des balises &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;, des balises &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; et du code de template HTML :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on:click=&lt;/span&gt;&lt;span class="s"&gt;{handleClick}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Clicked {count} {count === 1 ? 'time' : 'times'}
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Comme vu plus haut, le script qui apparait dans le fichier compilé n'est pas exactement ce qui a dans les balises script). &lt;/p&gt;

&lt;p&gt;On peut inclurer ses composant dans d'autres composants, en utilisant une notation comme celle du JSX:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
 &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;OtherComponent&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Component.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;OtherComponent&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Le style d'un composant n'impacte pas le style des composants qu'il inclut. &lt;/p&gt;

&lt;h2&gt;
  
  
  Props, Etat &amp;amp; Changement d'Etat
&lt;/h2&gt;

&lt;p&gt;L'état est défini dans des blocks, en utilisant comme  :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
 &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ceci déclare un état !&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;C'est pareil pour les props, c'est à dire les paramètres d'entrée des composants :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
 &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ceci déclare un props !&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Attention: Svelte a besoin &lt;strong&gt;d'immutabilité&lt;/strong&gt; pour gérer les changements d'état (ce qui est logique), ou plus exactement, j'ai l'impression qu'il a besoin qu'il y ait l'utilisation de l'opérateur = sur une variable qui a été déclarée avec un let, et que le compilateur sait qu'il doit surveiller. Si on change la valeur d'une des clefs dans un dictionnaire ou un array, le changement n'est pas détecté.    &lt;/p&gt;

&lt;h2&gt;
  
  
  Le templating html
&lt;/h2&gt;

&lt;p&gt;Svelte a une logique de templating dans le html. Il y a comme dans le JSX l'injection de valeurs, (&lt;code&gt;&amp;lt;p&amp;gt;Value is {x}&amp;lt;/p&amp;gt;&lt;/code&gt;), Mais aussi des blocks, qui commencent avec des  &lt;code&gt;{#}&lt;/code&gt;, finiseent avec des &lt;code&gt;{/}&lt;/code&gt; et comportent eventuellement des éléments intermédiaires en &lt;code&gt;{:}&lt;/code&gt; Ces blocks permettent d'écrire des conditions des boucles (&lt;code&gt;{#each}&lt;/code&gt;)  et des conditions &lt;code&gt;{#if ...}&lt;/code&gt;), Par exemple :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;{#if x &amp;gt; 10}
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;{x} is greater than 10&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
{:else if 5 &amp;gt; x}
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;{x} is less than 5&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
{:else}
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;{x} is between 5 and 10&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
{/if}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dans les boucles, on a le meme probleme de clef unique que la boucle d'objets de react : il faut spécifier l'id de la clef unique:&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;{#each items as item (item.id)}&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Il y a un troisième type de block, qui consiste à déclarer qu'on attent le retour d'une fonction asynchrone (une Promise, quoi) avec le bloc &lt;code&gt;{#await}&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Evenements &amp;amp; Bindings
&lt;/h2&gt;

&lt;p&gt;Autre particularité, pour gérer les clicks &amp;amp; co, on définit des event listeners sur les elements html avec des on: on:click, on:mousemove. On peut modifier ces events listeners avec par ex. |once ou |self (ne trigger qu'une seule fois, ne trigger que sur soi). On peut définir des event listeners pour connecter deux éléments, avec un émetteur et un récepteur. Ca me rappelle la joie de coder en ActionScript / Flash, au bon vieux temps des jeux sur Facebook !&lt;/p&gt;

&lt;p&gt;On utilise le même genre de notation pour dire qu'un élément HTML (comme un input par exemple) va impacter une variable, ce qui nous permet de faire une liaison à double sens entre l'affichage et l'état :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;bind:value=&lt;/span&gt;&lt;span class="s"&gt;{name}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Je crois que Vue a une notation un peu similaire)&lt;/p&gt;

&lt;h1&gt;
  
  
  En conclusion
&lt;/h1&gt;

&lt;p&gt;Pour être complet il y aurait évidemment tout un tas d'autre choses à mentionner comme les &lt;em&gt;stores&lt;/em&gt; (au sens anglais, pas français !) ou les transitions ou le &lt;em&gt;context&lt;/em&gt; (qui pour le coup ressemble un peu à celui de React). &lt;/p&gt;

&lt;p&gt;Pour moi il y a deux questions qui se posent. Est-ce que j'ai envie de continuer à apprendre ce framework ? Et est-ce que j'ai envie de m'en servir sur le plus long terme. &lt;/p&gt;

&lt;p&gt;Et pour moi, c'est l'originalité de Svelte, avec l'impact de la phase de compilation, qui me donne envie de l'apprendre, de comprendre comment il marche. &lt;/p&gt;

&lt;p&gt;Je ne sais par contre pas comment mes équipes, si je leur mettais du Svelte entre les mains, réagiraient. &lt;/p&gt;

</description>
      <category>svelte</category>
      <category>french</category>
    </item>
    <item>
      <title>Tutorial Next.JS + Tailwind : créer un blog</title>
      <dc:creator>David Hockley</dc:creator>
      <pubDate>Thu, 06 May 2021 05:21:10 +0000</pubDate>
      <link>https://dev.to/kodaps/tutorial-next-js-tailwind-creer-un-blog-4la5</link>
      <guid>https://dev.to/kodaps/tutorial-next-js-tailwind-creer-un-blog-4la5</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5qy4rro3m2rajt6unjmw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5qy4rro3m2rajt6unjmw.jpg" alt="Alt Text" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Je commence par installer Next.JS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-next-app nextjs-blog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Je crée un fichier tsconfig.json pour indiquer qu'on veut etre sous Typescript (et j'installe directement Typescript)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch tsconfig.json
yarn add --dev typescript @types/react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensuite c'est parti pour installer et initialiser Tailwind :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
npx tailwindcss init -p
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Puis j'édite le fichier globals.css pour inclure les fichiers de style de Tailwind.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* ./styles/globals.css */&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;utilities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;J'aime bien changer les fichier index.js et app.js en .tsx (mais ça ne change pas grand chose)&lt;/p&gt;

&lt;p&gt;Maintenant que l’initialisât ion est faite, posons les bases de notre blog.&lt;/p&gt;

&lt;p&gt;La première étape consiste à définir le type de l'article de blog, au sens Typescript. &lt;br&gt;
Pour cela je crée un dossier shared/, à la racine, dans lequel je met un fichier types.d.ts qui va servir à contenir les différents types. Je vais supposer qu'on veut charger d'autres types de données que juste des articles de blog (mais je ne sais pas encore quoi à ce stade, donc j'en fais peut etre un peu trop). Néanmoins je crée un type de base pour mon contenu, que je spécialise pour l'article de blog.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;BlogPost&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A présent je crée la page d'accueil du blog, en créant un fichier index.tsx, dans un dossier blog/ que je crée dans /pages. Ce fichier va servir à lister tous les articles de blog (quand il y en aura !)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/blog/index.tsx&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;BlogPagesProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;blogs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BlogPost&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BlogPages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BlogPagesProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;Blog Posts&lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;BlogPages&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A présent, allons chercher le contenu que nous allons lister. Pour ça, je commence par créer un dossier content, dans le quel je mets pour le moment un dossier blog/ (une fois de plus, ça suppose que j'ai d'autre contenu)&lt;/p&gt;

&lt;p&gt;Comment est-ce que ça fonctionne ? Dans une page on peut définir une fonction getStaticProps. Cette fonction sert pour le rendu côté serveur. Elle sert à récupérer toutes les données statiques qui utiles pour rendre la page. Typiquement si on voulait faire un appel à une base de données pour lister le contenu pertinent, c'est ici qu'on le ferait. Dans notre cas, nous allons lister tous les fichiers markdown (en .md) qui sont dans le dossier content/blog, et c'est ça qui nous servira de contenu. &lt;/p&gt;

&lt;p&gt;Le nom de fichier servira d'identifiant (de champ id), mais on veut pouvoir aussi définir un titre, qui servira dans la liste sur l'accueil du blog.  &lt;/p&gt;

&lt;p&gt;Un petit détail qui est sympa avec Markdown : on peut définir des (méta)données en entête, et les lire. Ca s'appelle le &lt;em&gt;front matter&lt;/em&gt;. C'est typiquement avec ça qu'on va pouvoir dire qui est l'auteur, ou quelle est l'image qu'on veut mettre en avant. &lt;/p&gt;

&lt;p&gt;Une lib existe pour les lire : gray-matter&lt;/p&gt;

&lt;p&gt;Ajouter gray-matter :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add gray-matter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Créer les fonctions de récupération des données :
&lt;/h2&gt;

&lt;p&gt;On va créer une fonction de récupération générique, qui lit un dossier et qui retourne bah.. un type de contenu.&lt;/p&gt;

&lt;p&gt;On va commencer par lister et lire tous les fichiers md qui sont dans un dossier donné:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;_getAllData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Get file names under folder&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileNames&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileNames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;fileName&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Remove ".md" from file name to get id&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;md$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Read markdown file as string&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fullPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileContents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fullPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Use gray-matter to parse the post metadata section&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;matterResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;matter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileContents&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;matterResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;matterResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}));&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alors je crée une fonction "factory", qui me fabrique la fonction en fonction du répertoire injecté :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;makeGetters&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;getAllData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;_getAllData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En suite on crée la version spécifique pour le blog :&lt;/p&gt;

&lt;p&gt;On crée un fichier &lt;code&gt;/shares/blog.ts&lt;/code&gt; tout simple&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;makeGetters&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;directory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content/blog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;makeGetters&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BlogPost&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Maintenant on référence cette page dans l'index du blog&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;BlogData&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../shared/blog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getStaticProps&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blogs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;BlogData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAllData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;blogs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;BlogPagesProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;blogs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BlogPost&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BlogPages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BlogPagesProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;blogs&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Blog Posts&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;blogs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;itm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;itm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;itm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;br&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&amp;lt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

  &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Et on teste : wundershön &lt;/p&gt;

&lt;p&gt;Et du coup maintenant on va aller créer la page qui va servir à faire les articles de blog eux mêmes &lt;/p&gt;

&lt;p&gt;Pour ça on crée un fichier &lt;code&gt;[id].tsx&lt;/code&gt; dans le dossier pages/blog&lt;/p&gt;

&lt;p&gt;En suite on fait la fonction qui récupère les données statiques en fonction de l'id&lt;/p&gt;

&lt;p&gt;Autrement dit cette fois ci au lieu de récupérer tous les fichiers on récupère le seul fichier dont l'id est dans le slug, le chemin.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;_getItemData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;extended&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fullPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.md`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileContents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fullPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Use gray-matter to parse the post metadata section&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;matterResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;matter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileContents&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;matterResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;matterResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* *** */&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;makeGetters&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;getItemData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;_getItemData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;getAllData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;_getAllData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensuite on définit dans types un paramètre&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;StaticRouteProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Et on crée le get static props de la page :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;PageProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BlogPost&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getStaticProps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;}:&lt;/span&gt;&lt;span class="nx"&gt;StaticRouteProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;BlogData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItemData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ici il y a une petite particularité. Dans la mesure ou c'est un chemin dynamique, on a besoin de savoir quels sont tous les contenus qu'il faut générer. Pour ça on a une fontion "getStaticPaths" qui en gros liste tous les contenus&lt;/p&gt;

&lt;p&gt;On retourne du coup dans content :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;_getAllIds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileNames&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fileNames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;md$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="cm"&gt;/***/&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;makeGetters&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;getAllIds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;_getAllIds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;getItemData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;_getItemData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;getAllData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;_getAllData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A présent dans le blog on définit la fonction getStaticPaths&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getStaticPaths&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;BlogData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAllIds&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A présent tout est prêt pour faire la page :&lt;/p&gt;

&lt;p&gt;On commence par importer Head, tout en haut :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Head&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/head&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Puis on crée la fin de la page :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;BlogPageProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BlogPost&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BlogPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BlogPageProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;BlogPage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Maintenant... il ne reste plus qu'à y accéder !&lt;/p&gt;

&lt;p&gt;Mettons à jour la page index du blog :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BlogPages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BlogPagesProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;blogs&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Blog Posts&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;blogs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;itm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;itm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/blog/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;itm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;itm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;br&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&amp;lt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

  &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On teste et ça marche mais ... c'est très moche. Heureusement on peut améliorer tout ça avec Tailwind, en ajoutant le plugin "typography" :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add @tailwindcss/typography
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensuite on édite tailwind.config.js pour rajouter le plugin :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;purge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;darkMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// or 'media' or 'class'&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;variants&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tailwindcss/typography&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;C'est tout de suite nettement plus beau ! &lt;/p&gt;

&lt;h1&gt;
  
  
  Rajouter une image 
&lt;/h1&gt;

&lt;p&gt;A présent j'aimerais bien rajouter une image. Dans NextJS les images sont prises depuis le dossier public. Donc je met l'image dans /public/blog &lt;/p&gt;

&lt;p&gt;Je rajoute l'info dans le font matter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tutorial&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Next.JS&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;+&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Tailwind&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;créer&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;un&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;blog"&lt;/span&gt;
&lt;span class="na"&gt;img&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;blog.jpg&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Je rajoute aussi l'information dans le type du blog. L'image est optionnelle donc je l'indique :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;BlogPost&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;img&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pour finir je rajoute l'image dans la page de l'article, en prenant en compte le fait que l'image peut etre absente (et donc je mets une condition sur l'image :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BlogPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BlogPageProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;article&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"prose lg:prose-xl mx-auto mt-12"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/blog/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ReactMarkdown&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ReactMarkdown&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;article&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Et voilà, on a un début de blog, qui a une bonne tête. &lt;/p&gt;

&lt;h1&gt;
  
  
  Etape finale : rajouter les méta datas 
&lt;/h1&gt;

&lt;p&gt;Un article de blog, c'est fait pour être partagé et découvert, non ? Mais pour que l'article soit bien compris par les moteurs de recherhe et bien formatté pour les réseaux sociaux, on peut rajouter des informations complémentaires ou "meta data". &lt;/p&gt;

&lt;p&gt;Pour ça Next met à disposition le composant head. &lt;/p&gt;

&lt;p&gt;On l'importe dans notre fichier [id].tsx&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Head&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/head&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;IL y a trois composants principaux aux metadatas : un titre, une image, une description. On a déjà les deux premiers, il nous manque le troisième. Du coup... on le rajoute dans le front-matter du markdown et dans le type de l'article de blog, comme on l'a fait pour l'image.  Ensuite on rajoute les infos dans notre composant (ceux sous la forme 'og:xxxxx' sont le format OpenGraph de Facebook mais ils sont aussi lus par Twitter. Ca nous donne :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BlogPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BlogPageProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="cm"&gt;/* ** etc. *** */&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; 
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; 
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt; 
            &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; 
            &lt;span class="na"&gt;property&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"og:title"&lt;/span&gt; 
            &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; 
            &lt;span class="na"&gt;property&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"og:description"&lt;/span&gt; 
            &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="si"&gt;{&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; 
            &lt;span class="na"&gt;property&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"og:image"&lt;/span&gt; 
            &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;}

    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* *** etc. *** */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;&amp;lt;/&amp;gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  In fine
&lt;/h1&gt;

&lt;p&gt;Voilà, vous avez avec ça les moyens de mettre en place un blog avec NextJS et TailwindCSS. Bon il reste encore pas mal de mise en page à faire sur la page principale et sur la page de présentation de la liste des articles de blog, sans parler de la navigation une fois qu'on est sur l'article, mais vous avez normalement les armes nécessaires pour le faire, ou sinon... n'hésitez pas si vous avez des commentaires ou des questions ! &lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>french</category>
      <category>tutorial</category>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>Effet Zoom de Medium en CSS + React</title>
      <dc:creator>David Hockley</dc:creator>
      <pubDate>Thu, 06 May 2021 05:04:37 +0000</pubDate>
      <link>https://dev.to/kodaps/effet-zoom-de-medium-en-css-avec-nextjs-8j5</link>
      <guid>https://dev.to/kodaps/effet-zoom-de-medium-en-css-avec-nextjs-8j5</guid>
      <description>&lt;p&gt;L’image d’un blog est un element clef des premières impressions que donne un article. Mais les images sont parfois lourdes à charger, et le temps de chargement est aussi intégral à la première impression. Comment concilier ces deux impératifs qui semblent antinomiques ?&lt;/p&gt;

&lt;p&gt;Le site Medium semble réussir à le faire, avec un effet sympa de zoom ou de flou et l’image qui apparaît (sans que du coup la mise en page ne saute). Comment est-ce qu’ils font ça ? Et surtout comment est-ce que nous on peut faire ça ?&lt;/p&gt;

&lt;p&gt;Voici une vidéo d'explication, pour le code détaillée, continuez à lire plus bas :)&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/roJwSL3kZnI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  Le principe de base 
&lt;/h1&gt;

&lt;p&gt;Pour faire cet effet-là, il y a trois choses à faire :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;créer une version basse qualité de l’image, un “Low Quality Image Placeholder” ou LQIP&lt;/li&gt;
&lt;li&gt;afficher cette image LQIP avec un filtre de flou &lt;/li&gt;
&lt;li&gt;sous cette image LQIP, avec exactement la même position et les mêmes dimensions, afficher l’image définitive&lt;/li&gt;
&lt;li&gt;mettre un évent listener qui se déclenche quand l’image finit de charger &lt;/li&gt;
&lt;li&gt;quand l’évent de déclenche changer l’état pour stocker le fait que le chargement est fait, et avec cet état, faire transitionner l’opacité de l’image basse qualité a 0&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Créer l’image basse qualité
&lt;/h1&gt;

&lt;p&gt;Pour ce genre de manipulation, je crée en général un dossier scripts/ dans lequel je met ... mes scripts.&lt;/p&gt;

&lt;p&gt;Pour ce script ci, qui va lister tous les fichiers jpg et en faire des versions basse définition, on a besoin de deux librairies : glob, qui permet de faire le listing des fichiers d’un dossier qui suivent une structure de nom de fichier (genre *.jpg) et sharp qui permet de faire de la manipulation d’image :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add glob sharp -D
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Les images que je veux manipuler sont dans le dossier /public/blog (puisque je suis sous NextJS), donc je les liste en ne prenant pas en compte ceux qui finissent en lqip.jpg, et je les redimensionne en 128 pixels de large. Pour ça je crée le script suivant dans scripts/updateImg.ts :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;glob&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;glob&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;sharp&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sharp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../public/blog/**/*.jpg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;er&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lqip.jpg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;sharp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.lqip.jpg`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// console.log(_data);&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Je rajoute un fichier package.json dans le dossier script pour pas qu'il me fasse d'erreur d’import&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lqipmaker"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"module"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;À présent passons a l’affichage des deux images &lt;/p&gt;

&lt;h1&gt;
  
  
  Positionnement des deux images
&lt;/h1&gt;

&lt;p&gt;Pour positionner les deux images l’une sur l’autre il nous faut les positionner chacune en absolu dans la même div.&lt;/p&gt;

&lt;p&gt;On positionne l'image initiale en top=0, left=0 avec un width de 100%;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CSSProperties&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;CSSProperties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;absolute&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On pourrait en faire de même pour l’image placeholder mais on veut faire un petit effet de zoom, et du coup on va agrandir l'image placeholder un peu. Pour être certain que l'image soit bien centrée, on va du coup la positionner non plus par rapport à son coin (ce que fait le top / left) mais par rapport à son &lt;strong&gt;centre&lt;/strong&gt;, qu'on place au centre de la div parente, en lui faisant un &lt;strong&gt;transform&lt;/strong&gt;. Pour finir, on applique une transition sur l'opacité pour permettre à l'image de disparaitre de manière animée (et donc faire apparaître l'image en dessous).  :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lqip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;CSSProperties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;absolute&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blur(10px)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;zIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;50%&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;50%&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;translate(-50%, -50%) scale(1.1)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;transitionDuration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;500ms&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;transitionProperty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;opacity&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;transitionTimingFunction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cubic-bezier(0.4, 0, 1, 1)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;objectFit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cover&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Le zoom nous permet aussi d'éviter le problème du blur qui fait des bords blancs bizarres. A présent il nous faut mettre des deux images dans une div parente. On va fixer &lt;strong&gt;l'aspect ratio&lt;/strong&gt; de cette div en 16/9e (en lui mettant un paddingBottom à '56.25%',) et cacher ce qui en déborde (avec un overflow: 'hiddden'). Et évidemment un position: 'relative' pour permettre le positionnement absolu des enfants.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;CSSProperties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;relative&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;paddingBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;56.25%&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;marginBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nous avons le chemin vers image dans une variable img, et allons donc également chercher l'image dont le chemin est : img + .lqip.jpg&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt;
      &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`/blog/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.lqip.jpg`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;lqip&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt;
      &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`/blog/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Gestion de l'état de chargement
&lt;/h1&gt;

&lt;p&gt;A présent nous allons créer dans notre composant un état pour stocker le fait ou non que l'image soit chargée :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;imageLoaded&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setImageLoaded&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On va changer cet état quand l'image ce charge, et changer l'opacité de la LQIP en fonction de si l'image est chargée ou non :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt;
      &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`/blog/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.lqip.jpg`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;lqip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;imageLoaded&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt;
      &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`/blog/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;onLoad&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setImageLoaded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mais quand fait un console.log de l'état de imageLoaded, celui-ci revient toujours false. Pourquoi ? Parce que l'image est en cache et que le chargement a lieu trop tôt. &lt;/p&gt;

&lt;p&gt;Comment résoudre cela ? Et bien nous allons déclencher le chargement de l'image après coup. &lt;/p&gt;

&lt;p&gt;On va commencer par créer un état qui correspond au chemin vers l'image :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;imgurl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setImgUrl&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensuite nous utilisons le chemin de l'image pour mettre à jour ce chemin, une fois le composant chargé :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setImgUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/blog/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pour finir, on remplace l'attribut src de l'image principale, pour qu'il soit donc affecté plus tard et que l'image charge plus tard :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;
     &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;imgurl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="nx"&gt;onLoad&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setImageLoaded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
   &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Et voila, un effet style Medium ou Gatsby sur une image dans NextJS / React !&lt;/p&gt;

&lt;p&gt;(Si vous avez des questions ou des remarques, n'hésitez pas !)&lt;/p&gt;

</description>
      <category>react</category>
    </item>
  </channel>
</rss>
