Désolé pour mon absence ces 3 derniers mois ! Je n'ai pas réussi à trouver le temps pour la rédaction de cette newsletter. C'est fou comment de si petits êtres peuvent vous accaparer autant de temps 👶 🤗
Mais je suis de retour pour rattraper le retard, donc voici les nouveautés et nouvelles qu'il ne fallait pas manquer sur l'écosystème React / Javascript, de Juillet, Août et Septembre 2022 🤗
Au programme, forcément un peu plus long :
- Bun, Deno, quand Node se fait bousculer !
- Docusaurus 2.0 est sorti !
- ViteJS 3.0
- NextJS 12.3, Remotion 3.1, Sandpack 1.8
- Un comparatif de performances avec 6 frameworks SSR
- Vous n'avez peut-être pas besoin d'un
useEffect
- A la découverte de
Object.freeze
&Object.seal
- Les outils / packages à surveiller
- WTF JS?
Bun, Deno, quand Node se fait bousculer !
On connaissait déjà Deno le runtime qui promettait d'envoyer Node à l'age de pierre. Deno adopte une série de changements qui devraient conduire à une adoption plus rapide. Dans les prochains mois, Deno permettra d'importer facilement les packages npm, rendant compatible la grande majorité des packages npm existants ! L'import d'un package npm serait aussi simple que
import express from "npm:express@5";
Ils annoncent également pour leur prochaine release majeure, un nouveau serveur http, qui sera le serveur le plus rapide jamais développé en JS
Mais voilà qu'un nouveau runtime challenger se joint à la bataille : Bun qui annonce simplement des performances entre 3x et 10x supérieures à Node et Deno ! Bun est de plus compatible avec les packages npm et embarque nativement des API Web comme fetch
, WebSocket
et ReadableStream
. Bun intégrant également nativement un transpiler, TypeScript
et <JSX>
fonctionnent nativement.
On pourrait se questionner sur l'interêt de tous ces runtimes. Personnellement je trouve que c'est une bonne chose, la "compétition" fait toujours avancer les choses. Je ne pense pas que ni Deno ni Bun puissent surpasser Node, mais ça aura au moins le mérite de faire bouger les cycles de développement de Node pour intégrer des fonctionnalités plus rapidement. De la même manière que des preact
, vue
, svelte
,.. donnent des coups de fouet à React
Docusaurus 2.0 est sorti !
Après 4 ans de travail, 75 alpha versions et 22 betas, Docusauraus 2.0 est finalement live ! Pour rappel, Docusaurus est un générateur de site statique très facile à utiliser, et performant. C'est le générateur qui propulse ce blog !
Personnellement, ayant découvert Docusauraus déjà en version 2.0-alphaX
je ne peux que saluer les améliorations de fonctionnalités, et stabilité, qu'il y a eu lors de mes 7 mois d'adoption. J'attend maintenant avec impatience la sortie de la version 3.0
qui apportera notamment le support de MDX@2
ViteJS 3.0
16 mois après la v2
voici la v3 de Vite! A priori pas de "gros" changement, mais une amélioration des performances, stabilité,... Pendant ce laps de temps, l'adoption de ViteJS a pris des proprtions énormes. SvelteKit, Astra, Hydrogen, Nuxt, Cypress, Vitest, Laravel, ViteRuby (pour ne citer qu'eux) ont tous décider d'utiliser Vite par défaut. Je vous avais également invité à migrer vers Vite pour vos développement React (créés avec create-react-app
) tant les améliorations de performance étaient significatives.
Je n'ai pas encore eu l'occasion de migrer vers vite@3
, et de regarder si cela corrigeait notamment mes problématiques lors du build de mon app React, mais je compte m'y pencher prochainement !
NextJS 12.3, Remotion 3.1, Sandpack 1.8
Plusieurs mises à jour parmi les gros framework / librairies.
On commence avec NextJS qui passe en vers 12.3
, qui apporte son lot d'améliorations QOL (Quality Of Life). En améliorant notamment son fast-refresh, les Image Component et le compilateur SWC qui sont maintenant stable. Vous pouvez lire l'article de blog par ici
Remotion la (formidable) librairie pour créer des vidéos en utilisant react passe en version 3.1
. Au menu le support des GIF, de TailwindCSS
et une amélioration de la prise en charge de Spring
. L'article complet par ici
Et on termine par Sandpack qui est sorti de sa phase de beta fin Mai. Sandpack est un toolkit qui permet de créer des éditeurs de code live (avec un rendu immediat de ce que vous codez) et propulsé par CodeSandbox. C'est ce package qui est utilisé dans mes articles de blog pour les passages de code interactifs
Un comparatif de performances avec 6 frameworks SSR
Enterspeed a effectué un comparatif des performances de 6 frameworks SSR, pour choisir sur lequel ils devaient partir pour lancer un nouveau projet. Pour ce faire, ils ont créé un mini site qu'ils ont déployé Netlify, sur 6 apps différentes donc, chacune correspondant à une technologie.
Rappelons rapidement ce que signifie SSR : Server Side Rendering. Vous pouvez retrouver les explications de ces sigles dans mon précédent article
Ces 6 frameworks sont Astro, Gatsby, Next.js, Nuxt 3, Remix et SvelteKit
Vous pouvez lire la methodologie complète et les étapes en suivant ce lien je vous présente juste en dessous leurs résultats avec Google Lighthouse
Astro | Gatsby | Next.js | Nuxt 3 | Remix | SvelteKit | |
---|---|---|---|---|---|---|
Date de création | Mars 2021 | Mai 2015 | Octobre 2016 | Mars 2021 | Octobre 2020 | Octobre 2020 |
⭐ sur Github | 18.2k | 53.4k | 91.8k | 8.7k | 19k | 10.1k |
Lighthouse Performance Score | 99.2 | 95.6 | 98.6 | 98.8 | 98.8 | 99 |
FCP (First Contentful Paint) | 0.8s | 0.8s | 0.9s | 1.1s | 0.8s | 0.9s |
Speed Index | 2.8s | 5.6s | 3.2s | 2.9s | 2.8s | 2.3s |
Largest Contentful Paint (LCP) | 0.8s | 1.9s | 1.2s | 1.2s | 1.2s | 0.9s |
Total Blocking Time (TBT) | 0ms | 28ms | 54ms | 20ms | 30ms | 36ms |
Time To First Byte (TTFB) | 137ms | 133ms | 63ms | 438ms | 136ms | 62ms |
Vous n'avez peut-être pas besoin d'un useEffect
Je vois passer dans les revues de code, aussi bien au sein des élèves de la Wild Code School, que sur Stack Overflow, une mauvaise utilisation des useEffect
. Dan Abramov s'est également emparé du sujet en rajoutant un tuto dans le "learning" de la nouvelle documentation React
L'idée à comprendre derrière est qu'un useEffect
doit être déclenché quand on a besoin d'effectuer un re-render du composant. Le calcul de variable servant à effectuer le render ne sont pas des effet et doivent être calculés pendant le render. Par exemple :
const MyComp = () => {
const [firstName, setFirstName] = useState('Taylor');
const [lastName, setLastName] = useState('Swift');
// 🔴 Avoid: redundant state and unnecessary Effect
const [fullName, setFullName] = useState('');
useEffect(() => {
setFullName(`${firstName} ${lastname}`);
}, [firstName, lastName]);
}
Ici fullName
n'a PAS besoin d'être calculé dans un useEffect
et défini dans un state. Cette logique provoquerait d'ailleurs un re-render supplémentaire, car après le premier render, le useEffect
sera exécuté, et provoquerait un nouveau re-render. Ici, il suffit de calculer fullName
pendant la phase de render
const MyComp = () => {
const [firstName, setFirstName] = useState('Taylor');
const [lastName, setLastName] = useState('Swift');
// ✅ Good: calculated during rendering
const fullName = `${firstName} ${lastname}`;
}
En cas de calcul "lourd", vous pourriez être tenté d'utiliser un useEffect
pour stocker le retour du calcul dans un state, et ainsi s'assurer que celui-ci ne soit pas ré-exécuté
const TodoList = ({ todos, filter }) => {
const [newTodo, setNewTodo] = useState('');
// 🔴 Avoid: redundant state and unnecessary Effect
const [visibleTodos, setVisibleTodos] = useState([]);
useEffect(() => {
setVisibleTodos(getFilteredTodos(todos, filter));
}, [todos, filter]);
}
De la même manière, ce n'est pas un "Effect" mais un calcul, il vous faut donc l'exécuter directement pendant la phase de render
const TodoList = ({ todos, filter }) => {
const [newTodo, setNewTodo] = useState('');
// ✅ This is fine if getFilteredTodos() is not slow.
const visibleTodos = getFilteredTodos(todos, filter);
}
Mais vous allez me dire que si le calcul requiert énormement de ressource, il va être ré-exécuté à chaque render, et vous avez raison. Dans ce cas, il faudra "cacher" (ou mémoriser) le résultat du calcul, pour ne l'exécuter qu'une seule fois
import { useMemo, useState } from 'react';
const TodoList = ({ todos, filter }) => {
const [newTodo, setNewTodo] = useState('');
// ✅ Does not re-run unless todos or filter change
const visibleTodos = useMemo(() => {
return getFilteredTodos(todos, filter);
}, [todos, filter]);
}
A la découverte de Object.freeze
& Object.seal
Un petit tuto rapide sur ces 2 méthodes freeze
et seal
.
Object.freeze
va permettre de geler un objet. C'est à dire qu'on ne pourra pas ajouter de nouvelles propriétés, ni de modifier ou supprimer les existantes
const obj = {
foo: 'bar'
}
Object.freeze(obj);
obj.foo = "baz";
obj.baz = "foo";
console.log(obj.foo) // 'bar'
console.log(obj.baz) // undefined
Object.seal
de son coté va sceller l'objet, ce qui veut dire que vous ne pourrez plus ajouter ou supprimer des propriétés, mais vous pourrez modifier les propriétés existantes
const obj = {
foo: 'bar',
bar: 'foo',
}
Object.seal(obj);
obj.foo = "baz";
obj.baz = "foo";
delete obj.bar;
console.log(obj.foo) // 'baz'
console.log(obj.baz) // undefined
console.log(obj.bar) // 'foo'
Les outils / packages à surveiller
- reassure Tests de performance pour React & React Native
- MillionJs Un virtual DOM qui se veut hyper léger (< 1 Ko) et 11x plus rapide que React
- Awesome React Components Une liste des meilleurs composants React, pour faire à peu près tout ce dont vous avez besoin !
- Firebase hooks Une librairie de Hooks pour interagir avec Firebase
- grex Un générateur de RegEx "inversé". Vous lui donnez vos tests cases, et il va (essayer) de se débrouiller pour trouver la RegEx qui match vos exemples
WTF JS?
Que va afficher ce console.log
?
console.log( true + true == true )
Afficher la solution et les explications !
😱 false
😱
Alors pourquoi ?
On va encore se trouver face à un problème de transtypage si cher à Javascript
Utiliser le +
en JS est toujours un petit challenge 😃 S'il y a 1 seul String
dans l'opération, tout va être transtypé en string
, puis vous allez concaténer les chaînes. S'il n'y a pas String
, c'est une opération mathématique. Et pour faire une opération mathématique, on transtype en Number
!
Et Number(true) === 1
. Donc nous avons 1 + 1 == 1
, ce qui est donc... false
😉
Ne manquez pas un article !
Envie de recevoir par email mes derniers articles et Recapt ?
Essayez de taper register <votre adresse email>
dans la console 🎉