Visión general de la base de código
Esta sección te dará una perspectiva general de la organización del código base de React, sus convenciones, e implementación.
Si quieres contribuir a React esperamos que esta guía te ayude a sentirte más cómodo al hacer cambios.
No recomendamos necesariamente alguna de estas convenciones en aplicaciones de React. Muchas de ellas existen por razones históricas y pueden cambiar con el tiempo.
Carpetas principales
Después de clonar el repositorio de React, verás algunas carpetas principales en él.
packages
contiene metadatos (como elpackage.json
) y el código fuente (subdirectoriosrc
) para todos los paquetes en el repositorio de React. Si tú cambio está relacionado con el código, el subdirectoriosrc
de cada paquete es donde pasarás la mayoría del tiempo.fixtures
contiene algunas aplicaciones pequeñas de prueba para colaboradores.- [
build
] es el compilado de React. No está en el repositorio pero aparecerá en la carpeta clonada de React después de que compiles por primera vez.
La documentación está en un repositorio aparte de React.
Hay otras carpetas principales pero son usadas como herramientas y no vas a necesitarlas al momento de contribuir.
Ubicación de las pruebas
No tenemos un carpeta principal para las pruebas unitarias. En cambio, están ubicadas en un directorio llamado __tests__
relativo a los archivos que prueban.
Por ejemplo, una prueba para setInnerHTML.js
está ubicada junto a __tests__/setInnerHTML-test.js
.
Advertencias e Invariantes
El código base de React utiliza console.error
para mostrar advertencias:
if (__DEV__) {
console.error('Something is wrong.');
}
Las advertencias solo están disponibles en desarrollo. En producción, se eliminan. Si necesitas prohibir la ejecución de un código, usa el módulo invariant
:
var invariant = require('invariant');
invariant(
2 + 2 === 4,
'You shall not pass!'
);
El invariante se muestra cuando la condición invariant
es false
.
“Invariante” es una forma de decir “está condición siempre es true”. Puedes pensar al respecto como si hicieras una comprobación.
Es importante mantener similar el comportamiento del ambiente de producción y desarrollo, de forma que la condición invariant
aplique para ambos. Los mensajes de error son reemplazados automáticamente por códigos de error en producción para evitar que afecten de forma negativa el tamaño en bytes.
Desarrollo y Producción
Puedes usar la variable seudo-global __DEV__
en el código base para proteger bloques de código únicamente en desarrollo.
Esta variable es agregada durante la fase de compilación, y se transforma en verificaciones de la forma process.env.NODE_ENV !== 'production'
en los compilados de CommonJS.
Para compilados independientes, se vuelve true
en el compilado no minificado, y se remueve por completo junto con los bloques if
que protege en el compilado minificado.
if (__DEV__) {
// Este código solo funcionará en desarrollo.
}
Flow
Recientemente se introdujeron validaciones Flow al código base. Archivos marcados con la anotación @flow
en el comentario de encabezado de la licencia se están validando.
Aceptamos pull requests para agregar anotaciones Flow al código existente. Las anotaciones Flow se ven así:
ReactRef.detachRefs = function(
instance: ReactInstance,
element: ReactElement | string | number | null | false,
): void {
// ...
}
Cuando sea posible, el nuevo código debería usar anotaciones Flow.
Puedes usar yarn flow
localmente para verificar tu código con Flow.
Múltiples paquetes
React es un monorepo. Su repositorio contiene múltiples paquetes separados de tal forma que sus cambios puedan coordinarse, y los issues se encuentren en un solo lugar.
Núcleo de React
El “núcleo” de React incluye todas las APIs principales de React, por ejemplo:
React.createElement()
React.Component
React.Children
El núcleo de React incluye las APIs necesarias para definir componentes. Este no incluye el algoritmo de reconciliación o cualquier código específico a una plataforma. Es usado por componentes de React DOM y React Native.
El código del núcleo de React está ubicado en packages/react
en el árbol de fuentes. Está disponible en npm como el paquete react. La compilación del navegador se llama react.js
, y exporta un global llamado React
.
Renderizadores
React fue creado originalmente para el DOM pero fue adaptado para dar soporte a plataformas nativas con React Native. Esto introdujo el concepto de “renderizadores” en React.
Los renderizadores gestionan cómo un árbol de React se convierte en llamados de la plataforma subyacente.
Los renderizadores también están ubicados en packages/
:
- Renderizador de React DOM renderiza componentes de React en el DOM. Implementa APIs principales de
ReactDOM
y está disponible como un paquete npmreact-dom
. También puede ser usado como un bundle independiente del navegador llamadoreact-dom.js
que exporta un global deReactDOM
. - Renderizador de React Native renderiza componentes de React en vistas nativas. Es usado internamente por React Native.
- Renderizador de pruebas de React renderiza componentes de React en árboles JSON. Es usada por la funcionalidad Snapshot Testing de Jest y está disponible como el paquete npm react-test-renderer.
Otro renderizador oficialmente soportado es react-art
. Antes estaba en un repositorio de GitHub separado pero lo movimos a la estructura principal de directorios por ahora.
Nota:
Técnicamente
react-native-renderer
es una capa delgada que enseña a React a interactuar con la implementación de React Native. El verdadero código espicífico a la plataforma que se encarga de las vistas nativas está en el repositorio de React Native junto con sus componentes.
Reconciliadores
Incluso los renderizadores como React DOM y React Native necesitan compartir una gran cantidad de lógica. En particular, el algoritmo de reconciliación debe ser tan similar como sea posible para que el renderizado declarativo, los componentes personalizados, el estado, los métodos del ciclo de vida, y las referencias funcionen de forma consistente a tráves de las plataformas.
Para resolver esto, diferentes renderizadores comparten parte del código entre sí. Llamamos a esta parte de React un reconciliador
. Cuando se planifica una actualización como setState()
, el reconciliador llama el método render()
en los componentes del árbol y los monta, actualiza, o desmonta.
Los reconciliadores no están empaquetados por separado porque actualmente no tienen una API pública. Por el contrario, son exclusivamente usados por los renderizadores como React DOM y React Native.
Reconciliador de pila
El reconciliador de “pila” es la implementación que permite el funcionamiento de React 15 y versiones previas. Dejamos de usarlo, pero está documentado en detalle en la próxima sección.
Reconciliador Fiber
El reconciliador “fiber” es un nuevo esfuerzo dedicado a resolver los problemas inherentes al reconciliador de pila y arreglar algunos issues. Ha sido el reconciliador por defecto desde React 16.
Sus objetivos principales son:
- Habilidad de dividir trabajo interrumplible en partes.
- Habilidad de priorizar, y reusar trabajo en progreso.
- Habilidad para moverse entre padres e hijos para soportar maquetación en React.
- Habilidad para retornar múltiples elementos desde el método
render()
. - Mejor soporte a límites de error.
Puedes leer más acerca de la Arquitectura de React Fiber aquí y aquí. Como el soporte comenzó desde React 16, las funcionalidades asíncronas no se han habilitado aún.
Su código fuente está ubicado en packages/react-reconciler
.
Sistema de Eventos
React implementa una capa sobre los eventos nativos para minimizar las diferencias entre navegadores. Su código fuente está localizado en packages/react-dom/src/events
.
¿Qué sigue?
Lee la próxima sección para aprender en más detalle acerca de la implementación del reconciliador antes de React 16. No hemos documentado los aspectos internos del nuevo reconciliador aún.