Aperçu du code source
Cette section vous donne un aperçu de l’organisation du code source de React, de ses conventions et de son implémentation.
Si vous souhaitez contribuer à React, nous espérons que ce guide vous aidera à vous sentir plus à l’aise pour apporter des modifications.
Nous ne recommandons pas nécessairement ces conventions dans les applications React. Nombre d’entre elles existent pour des raisons historiques et sont susceptibles d’évoluer avec le temps.
Dossiers racines
Après avoir cloné le dépôt React, vous verrez quelques dossiers racines :
packages
contient des métadonnées (telles quepackage.json
) et le code source (sous-répertoiresrc
) de tous les paquets du dépôt React. Si votre modification est liée au code, vous passerez le plus clair de votre temps dans le sous-répertoiresrc
des différents paquets.fixtures
contient quelques petites applications React de test pour les contributeurs.build
est la sortie de construction de React. Il ne figure pas dans le dépôt, mais il apparaîtra dans votre clone de React après que vous l’aurez construit pour la première fois.
La documentation est hébergée dans un dépôt distinct de React.
Il existe quelques autres dossiers racines, mais ils sont principalement utilisés par l’outillage et vous n’aurez probablement jamais affaire à eux lorsque vous contribuerez.
Tests colocalisés
Nous n’avons pas de répertoire racine pour les tests unitaires. Nous les plaçons plutôt dans un répertoire appelé __tests__
situé à côté des fichiers qu’ils testent.
Par exemple, un test pour setInnerHTML.js
sera placé juste à côté, dans __tests__/setInnerHTML-test.js
.
Avertissements et invariants
Le code source de React utilise console.error
pour afficher les avertissements :
if (__DEV__) {
console.error('Il y a un souci.');
}
Les avertissements ne sont activés que dans la phase de développement. En production, ils sont complètement retirés du code. Si vous avez besoin d’interdire l’exécution d’une partie de code, utilisez plutôt le module invariant
:
var invariant = require('invariant');
invariant(
2 + 2 === 4,
'Vous ne passerez pas !'
);
L’invariant est levé lorsque la condition de invariant
est false
.
Le terme « invariant » signifie simplement « cette condition est toujours vraie ». Vous pouvez voir ça comme une affirmation.
Pour les invariants, il est important d’avoir un comportement similaire en développement et en production, afin qu’ils soient levés dans les deux cas. Les messages d’erreur sont automatiquement remplacés par des codes d’erreur en production afin d’éviter toute incidence négative sur la taille (en octets) du fichier.
Développement et production
Vous pouvez utiliser la variable pseudo-globale __DEV__
dans le code source pour délimiter les blocs de code réservés au développement.
La variable est remplacée lors de la compilation et se transforme en contrôles process.env.NODE_ENV !== 'production'
dans les builds CommonJS.
Pour les versions autonomes, la variable devient true
dans la version non-minifiée du fichier produit, alors qu’elle est complètement effacée, ainsi que les blocs if
qu’elle contrôle, dans la version minifiée.
if (__DEV__) {
// Ce code va uniquement s’appliquer pendant le développement.
}
Flow
Nous avons récemment commencé à introduire des contrôles Flow dans le code source. Les fichiers marqués avec l’annotation @flow
dans le commentaire d’en-tête de licence sont soumis à vérification.
Nous acceptons les pull requests qui ajoutent des annotations Flow au code existant. Les annotations Flow ressemblent à ceci :
ReactRef.detachRefs = function(
instance: ReactInstance,
element: ReactElement | string | number | null | false,
): void {
// ...
}
Dans la mesure du possible, le nouveau code devrait utiliser des annotations Flow.
Vous pouvez exécuter yarn flow
localement pour vérifier votre code avec Flow.
Plusieurs paquets
React est un monorepo. Son dépôt contient plusieurs paquets distincts afin que leurs modifications puissent être coordonnées et que les problèmes puissent être signalés dans un seul et même endroit.
Le noyau de React
Le « noyau » de React inclut toutes les API React
de niveau racine, par exemple :
React.createElement()
React.Component
React.Children
Le noyau React n’inclut que les API nécessaires à la définition des composants. Il n’inclut pas l’algorithme de réconciliation ni aucun code spécifique à une plate-forme. Il est utilisé à la fois par les composants de React DOM et de React Native.
Le code pour le noyau React se trouve dans packages/react
au sein de l’arborescence source. Il est disponible sur npm via le module react
. La version autonome correspondante pour l’utilisation à même le navigateur est appelée react.js
, et exporte une variable globale appelée React
.
Moteurs de rendu
React a été créé à l’origine pour le DOM, mais il a ensuite été adapté pour prendre également en charge les plates-formes natives avec React Native. C’est ainsi qu’est né le concept de « moteurs de rendu » (renderers, terme que nous utiliserons sans italiques dans la suite de ce texte, NdT) au sein de React.
Les renderers gèrent la transformation d’une arborescence React en appels à la plate-forme sous-jacente.
Les renderers sont également situés dans packages/
:
- Le renderer de React DOM retranscrit les composants React dans le DOM. Il implémente les API
ReactDOM
racines et est disponible via le module npmreact-dom
. Il peut aussi être utilisé en tant que bundle autonome dans le navigateur, lequel est nomméreact-dom.js
et exporte une variable globaleReactDOM
. - Le renderer de React Native retranscrit les composants React sous forme de vues natives. Il est utilisé en interne par React Native.
- Le renderer de test de React retranscrit les composants React sous forme d’arbres JSON. Il est utilisé par la fonctionnalité d’instantanés (snapshots, NdT) de Jest et est disponible via le module npm react-test-renderer.
Le seul autre moteur de rendu officiellement pris en charge est react-art
. Auparavant, il se trouvait dans un dépôt GitHub séparé, mais nous l’avons déplacé dans l’arborescence source principale pour le moment.
Remarque
Techniquement, le
react-native-renderer
est une couche très mince qui apprend à React à interagir avec l’implémentation de React Native. Le véritable code spécifique à la plate-forme, qui gère les vues natives et fournit les composants, réside quant à lui dans le dépôt React Native.
Réconciliateurs
Même des moteurs de rendu très différents comme React DOM et React Native doivent partager beaucoup de logique. En particulier, l’algorithme de réconciliation doit être aussi similaire que possible afin que le rendu déclaratif, les composants personnalisés, l’état local, les méthodes de cycle de vie et les refs fonctionnent de manière cohérente sur toutes les plates-formes prises en charge.
Pour résoudre ce problème, différents moteurs de rendu partagent du code entre eux. Nous appelons cette partie de React un « réconciliateur ». Lorsqu’une mise à jour telle que setState()
est planifiée, le réconciliateur appelle render()
sur les composants de l’arborescence et les monte, les met à jour ou les démonte.
Les réconciliateurs ne font pas l’objet de modules séparés, car ils ne disposent actuellement d’aucune API publique. Ils sont exclusivement utilisés par les moteurs de rendu tels que React DOM et React Native.
Réconciliateur Stack
Le réconciliateur “stack” est l’implémentation qui sous-tend React 15 et les versions antérieures. Nous avons depuis cessé de l’utiliser, mais il reste décrit en détail dans la prochaine page.
Réconciliateur Fiber
Le réconciliateur “fiber” représente une nouvelle tentative de résoudre les problèmes inhérents au réconciliateur “stack” en plus de quelques problèmes anciens. C’est le réconciliateur par défaut depuis React 16.
Ses objectifs principaux sont :
- la capacité à diviser un travail interruptible en segments ;
- la capacité à hiérarchiser, déplacer et réutiliser des travaux en cours ;
- la capacité à jongler entre parents et enfants pour exécuter une mise en page avec React ;
- la capacité à renvoyer plusieurs éléments depuis
render()
; - une meilleure prise en charge des périmètres d’erreur.
Vous pouvez en apprendre davantage sur l’architecture React Fiber ici et ici. Bien qu’elles soient livrées avec React 16, les fonctionnalités asynchrones ne sont pas encore activées par défaut.
Son code source est situé dans packages/react-reconciler
.
Système d’événements
React implémente une abstraction par-dessus les événements natifs afin de lisser les disparités d’un navigateur à l’autre. Son code source se trouve dans packages/react-dom/src/events
.
Et maintenant ?
Lisez la prochaine page pour en apprendre davantage sur l’implémentation du réconciliateur utilisé avant React 16. Nous n’avons pas encore documenté les détails internes d’implémentation du nouveau réconciliateur.