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 :
packagescontient 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épertoiresrcdes différents paquets.fixturescontient quelques petites applications React de test pour les contributeurs.buildest 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.ComponentReact.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
ReactDOMracines 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.jset 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-rendererest 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.