1. Architecture Overview
React is a monorepo containing the core UI library, multiple renderers, a scheduler, a compiler, developer tools, and supporting packages. The architecture separates the platform-agnostic reconciliation algorithm from platform-specific rendering, allowing React to target the DOM, native mobile, canvas, server-streamed HTML, and custom host environments through the same core engine.
High-Level Architecture
┌─────────────────────────────────────────────────────────────────┐
│ User Application │
│ Components, Hooks, JSX, Server/Client boundaries │
└────────────────────────────┬────────────────────────────────────┘
│
┌────────────────────────────▼────────────────────────────────────┐
│ react (core package) │
│ createElement, hooks API, Component/PureComponent, │
│ createContext, memo, lazy, forwardRef, Suspense, Fragment, │
│ Activity, ViewTransition, startTransition, cache, use │
└────────────────────────────┬────────────────────────────────────┘
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌────────────────┐ ┌────────────────┐ ┌────────────────────────┐
│ react-dom │ │ react-native- │ │ react-test-renderer │
│ (DOM renderer)│ │ renderer │ │ react-art │
│ │ │ │ │ react-noop-renderer │
│ Client: │ │ Fabric bridge │ │ (testing & canvas) │
│ createRoot │ │ to native host │ └────────────────────────┘
│ hydrateRoot │ └────────────────┘
│ Server: │
│ renderTo* │
│ Fizz (stream) │
└────────┬───────┘
│
┌────────▼───────────────────────────────────────────────────────┐
│ react-reconciler (Fiber) │
│ Work loop, fiber tree, hooks dispatcher, commit phase, │
│ Suspense, transitions, lanes-based priority, effects │
└────────────────────────────┬───────────────────────────────────┘
│
┌────────────────────────────▼───────────────────────────────────┐
│ scheduler │
│ Cooperative scheduling: priority queue (min-heap), │
│ MessageChannel-based yielding, 5 priority levels │
└────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────┐
│ React Server Components (Flight) │
│ react-server + react-server-dom-{bundler}/ │
│ Webpack, Turbopack, Parcel, ESM, Unbundled │
│ Server → Client streaming protocol │
└──────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────┐
│ React Compiler (babel-plugin) │
│ HIR → SSA → Type Inference → Reactive Scopes │
│ → Code Generation with automatic memoization │
└──────────────────────────────────────────────────┘
Component Inventory
| Component | Path | Role |
|---|---|---|
react |
packages/react/ |
Core API: hooks, components, elements, context |
react-dom |
packages/react-dom/ |
DOM renderer: client (createRoot, hydrateRoot) and server (Fizz streaming) |
react-dom-bindings |
packages/react-dom-bindings/ |
DOM-specific event system, property operations, Fizz instruction sets |
react-reconciler |
packages/react-reconciler/ |
Platform-agnostic Fiber reconciler (81 files, 1.6M chars — the largest package) |
scheduler |
packages/scheduler/ |
Cooperative task scheduler with priority queue |
react-server |
packages/react-server/ |
Flight server: Server Components rendering and streaming (37 files, 676K chars) |
react-client |
packages/react-client/ |
Flight client: deserialize server component streams |
react-server-dom-webpack |
packages/react-server-dom-webpack/ |
Flight integration for Webpack bundler |
react-server-dom-turbopack |
packages/react-server-dom-turbopack/ |
Flight integration for Turbopack bundler |
react-server-dom-parcel |
packages/react-server-dom-parcel/ |
Flight integration for Parcel bundler |
react-server-dom-esm |
packages/react-server-dom-esm/ |
Flight integration for native ESM |
react-server-dom-unbundled |
packages/react-server-dom-unbundled/ |
Flight integration without bundler (Node.js loader) |
react-native-renderer |
packages/react-native-renderer/ |
React Native Fabric renderer |
react-test-renderer |
packages/react-test-renderer/ |
Test renderer for snapshot testing |
react-noop-renderer |
packages/react-noop-renderer/ |
No-op renderer for internal reconciler testing |
react-art |
packages/react-art/ |
Canvas/SVG renderer via ART library |
react-is |
packages/react-is/ |
Runtime type checking for React element types |
react-refresh |
packages/react-refresh/ |
Fast Refresh (hot reloading) runtime |
react-cache |
packages/react-cache/ |
Experimental caching primitive |
react-markup |
packages/react-markup/ |
Static HTML markup rendering |
react-debug-tools |
packages/react-debug-tools/ |
Hook inspection for DevTools |
react-devtools |
packages/react-devtools/ |
Standalone DevTools app (Electron) |
react-devtools-core |
packages/react-devtools-core/ |
Core DevTools backend/frontend bridge |
react-devtools-shared |
packages/react-devtools-shared/ |
Shared DevTools UI, backend fiber inspection, hook parsing |
react-devtools-extensions |
packages/react-devtools-extensions/ |
Browser extension builds (Chrome, Firefox, Edge) |
react-devtools-inline |
packages/react-devtools-inline/ |
Embeddable DevTools (for sandboxes) |
react-devtools-timeline |
packages/react-devtools-timeline/ |
Scheduling profiler timeline view |
react-devtools-fusebox |
packages/react-devtools-fusebox/ |
React Native DevTools Fusebox integration |
eslint-plugin-react-hooks |
packages/eslint-plugin-react-hooks/ |
ESLint rules: rules-of-hooks, exhaustive-deps |
use-sync-external-store |
packages/use-sync-external-store/ |
Backward-compatible shim for external store subscriptions |
use-subscription |
packages/use-subscription/ |
Subscription hook (legacy, superseded by useSyncExternalStore) |
shared |
packages/shared/ |
Shared utilities, feature flags, React element types, version |
dom-event-testing-library |
packages/dom-event-testing-library/ |
Synthetic event dispatching for tests |
internal-test-utils |
packages/internal-test-utils/ |
Internal testing helpers |
jest-react |
packages/jest-react/ |
Jest matchers for React |
babel-plugin-react-compiler |
compiler/packages/babel-plugin-react-compiler/ |
React Compiler: Babel plugin for automatic memoization |
eslint-plugin-react-compiler |
compiler/packages/eslint-plugin-react-compiler/ |
ESLint rules for React Compiler diagnostics |
react-compiler-runtime |
compiler/packages/react-compiler-runtime/ |
Runtime support for compiler output (c() memo cache) |
react-compiler-healthcheck |
compiler/packages/react-compiler-healthcheck/ |
CLI tool to assess codebase compiler readiness |
react-mcp-server |
compiler/packages/react-mcp-server/ |
MCP server for compiler integration |
react-forgive |
compiler/packages/react-forgive/ |
Fault-tolerant compiler mode (server + client) |
snap |
compiler/packages/snap/ |
Snapshot testing for compiler output |
Technology Stack
| Layer | Technology |
|---|---|
| Language | JavaScript (Flow-typed), TypeScript (compiler packages) |
| Module system | CommonJS + ES Modules (dual builds) |
| Build | Rollup (bundles), Babel (transforms), tsup (compiler TS packages) |
| Type checking | Flow (core packages), TypeScript (compiler) |
| Testing | Jest, Playwright (compiler playground E2E) |
| Package management | Yarn 1.22.22 workspaces |
| Formatting | Prettier |
| Linting | ESLint with custom rules (scripts/eslint-rules/) |
| CI | Custom scripts in scripts/ci/ |
Data Flow: Component Render Cycle
1. State update (setState/dispatch/transition)
│
2. Scheduler enqueues work at appropriate priority lane
│
3. Reconciler begins render phase (pure, interruptible)
├── Walks fiber tree top-down
├── Calls function components (runs hooks)
├── Diffs old vs new children (reconcileChildFibers)
└── Builds work-in-progress fiber tree
│
4. Commit phase (synchronous, non-interruptible)
├── Before-mutation: snapshot lifecycle, ref detach
├── Mutation: DOM insertions, updates, deletions
└── Layout: useLayoutEffect, ref attachment, callbacks
│
5. Passive effects (useEffect) run asynchronously after paint
2. System Requirements
Development Environment
| Requirement | Version |
|---|---|
| Node.js | 14.17.0+ (18+ recommended) |
| Yarn | 1.22.22 (workspace-based monorepo) |
| Flow | 0.279.0 (core packages type checking) |
| TypeScript | 5.4.3+ (compiler packages) |
| Python | Not required |
| OS | macOS, Linux, Windows |
Runtime Requirements
React has no server-side runtime requirements — it is a client-side library that runs in any ES2015-compatible JavaScript environment. For server rendering:
| Environment | Requirements |
|---|---|
| Node.js SSR | Node.js 18+ (for renderToPipeableStream) |
| Edge SSR | Web Streams API support (renderToReadableStream) |
| React Native | React Native 0.73+ for Fabric renderer |
Note
The monorepo's
package.jsonspecifies"packageManager": "yarn@1.22.22". Using npm or pnpm to manage the monorepo workspace is not supported.
3. Configuration Reference
Feature Flags
React's behavior varies by release channel. Feature flags are defined in packages/shared/ReactFeatureFlags.js and overridden per-channel in packages/shared/forks/:
| Flag Pattern | Location | Purpose |
|---|---|---|
ReactFeatureFlags.js |
packages/shared/ |
Default flag values |
ReactFeatureFlags.www.js |
packages/shared/forks/ |
Facebook WWW overrides |
ReactFeatureFlags.native-oss.js |
packages/shared/forks/ |
React Native OSS |
ReactFeatureFlags.native-fb.js |
packages/shared/forks/ |
React Native Facebook |
ReactFeatureFlags.test-renderer.js |
packages/shared/forks/ |
Test renderer |
The scripts/flags/flags.js utility validates flag consistency across channels:
yarn flags
Build Environment Variables
| Variable | Purpose | Used In |
|---|---|---|
NODE_ENV |
development or production — controls warning inclusion |
Build output |
RELEASE_CHANNEL |
stable, experimental, www-modern, www-classic |
scripts/rollup/build.js |
REACT_VERSION |
Override React version in test transforms | scripts/babel/ |
CI |
CI environment detection | Playwright config, build scripts |
CI_TOTAL / CI_INDEX |
Shard builds across CI workers | scripts/rollup/build.js |
BUNDLES_FILTER |
Filter which bundles to build (comma-separated) | scripts/rollup/bundles.js |
VARIANT |
Test variant selection | scripts/jest/ |
React DevTools Environment Variables
| Variable | Default | Purpose |
|---|---|---|
REACT_DEVTOOLS_PORT |
8097 |
WebSocket server port for standalone DevTools |
REACT_DEVTOOLS_PATH |
(none) | Custom path to DevTools frontend |
REACT_DEVTOOLS_CLIENT_HOST |
(none) | Custom WebSocket client host |
REACT_DEVTOOLS_CLIENT_PORT |
(none) | Custom WebSocket client port |
REACT_DEVTOOLS_CLIENT_USE_HTTPS |
(none) | Enable HTTPS for DevTools WebSocket |
DEVTOOLS_VERSION |
(auto) | Version string for extension builds |
EDITOR_URL |
(none) | URL template for opening files in editor |
LOGGING_URL |
(none) | Telemetry endpoint for DevTools |
IS_CHROME / IS_FIREFOX / IS_EDGE |
(none) | Target browser for extension build |
FEATURE_FLAG_TARGET |
(none) | Feature flag channel for DevTools |
Important
REACT_EDITOR(or fallbackVISUAL/EDITOR) controls which editor React DevTools opens when you click a component's source location. Set it to your editor's CLI command (e.g.,code,vim,webstorm).
React Compiler Configuration
The compiler accepts options via the Babel plugin configuration:
// babel.config.js
module.exports = {
plugins: [
['babel-plugin-react-compiler', {
// EnvironmentConfig options
// See compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts
}],
],
};
Key compiler options are validated via Zod schemas in Environment.ts. The compiler validates Rules of React at compile time:
| Validation | File | What It Checks |
|---|---|---|
validateHooksUsage |
Validation/ValidateHooksUsage.ts |
Hooks called at top level only |
validateNoRefAccessInRender |
Validation/ValidateNoRefAccessInRender.ts |
No ref reads during render |
validateNoSetStateInRender |
Validation/ValidateNoSetStateInRender.ts |
No setState calls during render |
validatePreservedManualMemoization |
Validation/ValidatePreservedManualMemoization.ts |
Existing useMemo/useCallback preserved |
validateNoCapitalizedCalls |
Validation/ValidateNoCapitalizedCalls.ts |
Capitalized calls treated as components |
validateUseMemo |
Validation/ValidateUseMemo.ts |
useMemo dependency correctness |
ESLint Plugin Configuration
// eslint.config.js (flat config)
import reactHooks from 'eslint-plugin-react-hooks';
export default [
{
plugins: { 'react-hooks': reactHooks },
rules: {
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
},
},
];
Note
eslint-plugin-react-hooksrequires ESLint 7+ and supports up to ESLint 10 (GitHub #35758 tracks peerDependency updates for ESLint 10 support).
Scheduler Priority Levels
Defined in packages/scheduler/src/SchedulerPriorities.js:
| Priority | Value | Timeout | Use Case |
|---|---|---|---|
ImmediatePriority |
1 | -1 (sync) | Discrete events (click, key) |
UserBlockingPriority |
2 | 250ms | Continuous events (scroll, hover) |
NormalPriority |
3 | 5000ms | Default for renders |
LowPriority |
4 | 10000ms | Deferred work |
IdlePriority |
5 | maxSafeInt | Background work |
The scheduler yields to the browser every frameYieldMs (5ms) to maintain responsive input handling.
4. Deployment & Scaling
Building React from Source
# Clone the repository
git clone https://github.com/facebook/react.git
cd react
# Install dependencies (must use Yarn)
yarn install
# Build all release channels
yarn build
# Build specific packages
node ./scripts/rollup/build.js react/index,react-dom/index --type=NODE_DEV
# Build for DevTools development
yarn build-for-devtools-dev
Tip
Use
BUNDLES_FILTERto build only specific bundles during development:BUNDLES_FILTER=react-dom node ./scripts/rollup/build.js
Build Types
| Type | Description | Output |
|---|---|---|
NODE_DEV |
Node.js development (includes warnings) | build/node_modules/*/cjs/*.development.js |
NODE_PROD |
Node.js production (minified) | build/node_modules/*/cjs/*.production.js |
NODE_ES2015 |
Node.js ES2015+ | build/node_modules/*/cjs/*.production.js |
ESM_DEV / ESM_PROD |
ES Modules | build/node_modules/*/esm/*.js |
UMD_DEV / UMD_PROD |
UMD (browser globals) | build/node_modules/*/umd/*.js |
FB_WWW_DEV / FB_WWW_PROD |
Facebook internal | build/facebook-www/*.js |
RN_OSS_DEV / RN_OSS_PROD |
React Native OSS | build/react-native/ |
RN_FB_DEV / RN_FB_PROD |
React Native Facebook | build/react-native/ |
Release Channels
| Channel | Stability | npm Tag | Feature Flags |
|---|---|---|---|
| Stable | Production-ready | latest |
Conservative defaults |
| Experimental | Unstable, preview features | experimental |
All features enabled |
| Canary | Between stable and experimental | canary |
Most features enabled |
| WWW | Facebook internal | Not published | Custom overrides |
| React Native | Mobile | Not published separately | Platform-specific |
Publishing
Releases are automated via CI. Manual steps:
# Validate build output
yarn lint-build
# Run version checks
yarn version-check
# Download and verify an experimental build
yarn download-build
React Compiler Deployment
The compiler can be deployed as a Babel plugin in any build pipeline:
# Install
npm install babel-plugin-react-compiler react-compiler-runtime
# For React < 19, the runtime polyfill is required
npm install react-compiler-runtime
The react-compiler-runtime package provides the c() function (memo cache) as a polyfill for React versions below 19. React 19+ includes __COMPILER_RUNTIME natively.
Compiler Playground
The compiler includes a web-based playground at compiler/apps/playground/:
cd compiler
yarn install
yarn dev
Deployed automatically to Vercel on every push.
5. Operations
Running Tests
# Run all tests
yarn test
# Run tests for a specific release channel
yarn test-stable
yarn test-www
# Run tests for built artifacts
yarn test --build
# Run DevTools tests
yarn test-build-devtools
# Run DOM fixture tests
yarn test-dom-fixture
Note
Jest is not run directly — use
yarn testwhich invokesscripts/jest/jest-cli.js. This script handles release channel selection, feature flag injection, and test environment setup.
Test Environment Variables
| Variable | Purpose |
|---|---|
IS_BUILD |
Run tests against built artifacts instead of source |
VARIANT |
Select test variant |
TZ |
Timezone override (set to US/Pacific in global setup) |
REACT_CLASS_EQUIVALENCE_TEST |
Enable class/function component equivalence tests |
JEST_ENABLE_SOURCE_MAPS |
Enable source maps in test output |
Type Checking
# Run Flow type checking
yarn flow
# Run Flow for CI (with inlined host configs)
yarn flow-ci
# Generate Flow configs for package-specific host configs
yarn postinstall
Tip
Flow configuration is auto-generated by
scripts/flow/createFlowConfigs.jsduringpostinstall. Each renderer gets its own.flowconfigwith the correct host config inlined.
Linting
# Lint changed files
yarn linc
# Lint all files
yarn lint
# Format with Prettier
yarn prettier-all
# Check formatting
yarn prettier-check
Error Code Extraction
React uses numeric error codes in production to minimize bundle size. Error messages are mapped in scripts/error-codes/codes.json:
# Extract new error codes from source
yarn extract-errors
Changelog Generation
# Generate changelog between versions
yarn generate-changelog
The changelog generator (scripts/tasks/generate-changelog/) supports --codex and --claude flags for AI-assisted changelog writing, and --debug for verbose output.
Monitoring Build Health
# Validate built bundles for correctness
yarn lint-build
# Check module structure
node scripts/rollup/validate/index.js
6. Performance
Reconciler Performance Model
The Fiber reconciler uses a lanes model for priority scheduling:
- Each update is assigned a lane (bit in a 31-bit integer)
- Lanes represent priority levels (sync, default, transition, idle)
- The work loop processes one lane group at a time
- Higher-priority lanes can interrupt lower-priority work
- The
shouldYieldToHost()check runs every 5ms to maintain UI responsiveness
Scheduler Implementation
The scheduler (packages/scheduler/src/) uses:
- Min-heap priority queue (
SchedulerMinHeap.js): O(log n) insertion and extraction - MessageChannel for yielding: avoids
setTimeoutminimum delay - Task expiration: each priority level has a timeout; expired tasks are treated as synchronous
- Profiling support: optional event log buffer for the DevTools timeline
Bundle Size Optimization
| Technique | Implementation |
|---|---|
| Dead code elimination | __DEV__ guards stripped in production builds |
| Error code extraction | Production errors are numeric; full messages only in dev |
| Tree shaking | ES module builds support tree shaking |
| Multiple entry points | Separate builds for client, server, profiling |
| Closure Compiler | Used for Facebook WWW builds |
Concurrent Features
| Feature | Mechanism | Effect |
|---|---|---|
| Automatic batching | Multiple setState calls merged into one render | Fewer renders |
| Transitions | startTransition marks updates as non-urgent |
Unblocked input |
| Suspense | Pauses render while data loads, shows fallback | No waterfalls |
| Deferred values | useDeferredValue delays non-critical updates |
Smooth scrolling |
| Streaming SSR | renderToPipeableStream flushes HTML in chunks |
Faster TTFB |
7. Security
XSS Prevention
React auto-escapes all values embedded in JSX by default. This prevents cross-site scripting for the most common case:
// Safe — React escapes the value
<div>{userInput}</div>
// DANGEROUS — bypasses escaping
<div dangerouslySetInnerHTML={{ __html: userInput }} />
Caution
dangerouslySetInnerHTMLbypasses React's XSS protection entirely. Only use it with sanitized HTML from a trusted source. Never pass user input directly.
URL Sanitization
React warns when a javascript: URL is passed to href or src attributes and blocks the navigation in development mode.
Supply Chain
- The repository is MIT-licensed
- Dependencies are pinned via
yarn.lockandresolutionsinpackage.json jsdomis pinned to22.1.0via resolutions to avoid upstream issues- Internal packages use
link:and workspace dependencies to avoid npm registry exposure
Server Components Security
'use server'functions are exposed as RPC endpoints — validate all inputs'use client'marks the serialization boundary — props must be serializable- Server Component output is a Flight protocol stream, not raw HTML — it goes through React's sanitization
8. Developer Internals
Repository Structure
facebook/react/
├── packages/ # All npm-publishable packages
│ ├── react/ # Core API (hooks, elements, components)
│ │ ├── src/ # Source (27 files, 95K chars)
│ │ │ ├── ReactClient.js # Client-side exports
│ │ │ ├── ReactServer.js # Server Component exports
│ │ │ ├── ReactHooks.js # Hook dispatch to reconciler
│ │ │ ├── ReactBaseClasses.js # Component, PureComponent
│ │ │ ├── ReactElement.js # createElement, JSX runtime
│ │ │ ├── ReactContext.js # createContext
│ │ │ ├── ReactLazy.js # lazy() implementation
│ │ │ ├── ReactMemo.js # memo() implementation
│ │ │ └── ReactAct.js # act() for testing
│ │ └── npm/ # Build output structure
│ ├── react-dom/ # DOM renderer
│ │ ├── src/ # DOM-specific code
│ │ ├── client.js # createRoot, hydrateRoot
│ │ ├── server.js # renderToPipeableStream, etc.
│ │ └── static.js # prerender
│ ├── react-dom-bindings/ # DOM event system, property ops
│ │ └── src/
│ │ ├── client/ # DOM property operations
│ │ ├── events/ # Synthetic event system (23 files)
│ │ ├── server/ # Fizz instruction set
│ │ └── shared/ # Shared DOM utilities
│ ├── react-reconciler/ # Fiber reconciler (81 files, 1.6M chars)
│ │ └── src/
│ │ ├── ReactFiberBeginWork.js # Render phase entry
│ │ ├── ReactFiberCommitWork.js # Commit phase
│ │ ├── ReactFiberHooks.js # Hook implementations
│ │ ├── ReactFiberReconciler.js # Public reconciler API
│ │ ├── ReactChildFiber.js # Child reconciliation
│ │ ├── ReactFiberWorkLoop.js # Work loop scheduler integration
│ │ ├── ReactFiberLane.js # Lane priority model
│ │ └── ReactFiberConfig.js # Host config interface (shimmed per renderer)
│ ├── react-server/ # Flight server (37 files, 676K chars)
│ │ └── src/
│ │ └── flight/ # Server Component rendering
│ ├── react-client/ # Flight client (14 files, 256K chars)
│ │ └── src/ # Stream deserialization
│ ├── scheduler/ # Cooperative scheduler
│ │ └── src/
│ │ ├── SchedulerMinHeap.js # Min-heap priority queue
│ │ ├── SchedulerPriorities.js # 5 priority levels
│ │ └── SchedulerProfiling.js # Timeline profiling
│ ├── shared/ # Shared utilities (35 files, 98K chars)
│ │ ├── ReactFeatureFlags.js # Feature flag defaults
│ │ ├── ReactSymbols.js # Element type symbols
│ │ ├── ReactTypes.js # Flow type definitions
│ │ ├── ReactVersion.js # Version string
│ │ └── forks/ # Per-channel flag overrides
│ ├── react-devtools-shared/ # DevTools core (20 files, 160K chars)
│ └── ... # Other packages
├── compiler/ # React Compiler
│ ├── packages/
│ │ ├── babel-plugin-react-compiler/ # Main compiler plugin
│ │ │ └── src/
│ │ │ ├── Babel/ # Babel integration
│ │ │ ├── Entrypoint/ # Plugin options, pipeline entry
│ │ │ ├── HIR/ # High-level IR (control flow graph)
│ │ │ ├── SSA/ # Static single assignment
│ │ │ ├── Optimization/ # Constant propagation, DCE
│ │ │ ├── Inference/ # Mutation/aliasing analysis
│ │ │ ├── TypeInference/ # Type inference
│ │ │ ├── ReactiveScopes/ # Memoization scope construction
│ │ │ ├── Validation/ # Rules of React validation
│ │ │ ├── Transform/ # AST transforms
│ │ │ ├── Flood/ # Data flow analysis
│ │ │ └── Utils/ # Shared utilities
│ │ ├── eslint-plugin-react-compiler/
│ │ ├── react-compiler-runtime/
│ │ ├── react-compiler-healthcheck/
│ │ ├── react-mcp-server/ # MCP integration
│ │ ├── react-forgive/ # Fault-tolerant mode
│ │ ├── snap/ # Snapshot testing
│ │ └── make-read-only-util/
│ └── apps/
│ └── playground/ # Compiler playground (Next.js)
├── fixtures/ # Integration test apps
│ ├── flight/ # Server Components demo
│ ├── fizz/ # Streaming SSR demo
│ ├── ssr/ # Classic SSR demo
│ ├── dom/ # DOM behavior fixtures
│ ├── devtools/ # DevTools regression fixtures
│ └── ...
├── scripts/ # Build, test, CI tooling
│ ├── rollup/ # Build configuration (11 files, 133K chars)
│ │ ├── build.js # Main build orchestrator
│ │ ├── bundles.js # Bundle definitions
│ │ ├── wrappers.js # Module wrapper generation
│ │ └── plugins/ # Custom Rollup plugins
│ ├── jest/ # Test configuration (25 files, 57K chars)
│ ├── flow/ # Flow configuration generation
│ ├── babel/ # Custom Babel transforms
│ ├── error-codes/ # Error code extraction
│ ├── ci/ # CI scripts
│ ├── flags/ # Feature flag management
│ ├── eslint-rules/ # Custom ESLint rules
│ └── shared/ # Shared script utilities
└── flow-typed/ # Flow type definitions for dependencies
Architecture Deep Dive: Fiber Reconciler
The reconciler (packages/react-reconciler/src/, 81 files, 1.6M source chars) is the heart of React. Key files:
ReactFiberWorkLoop.js — The main work loop. Coordinates scheduling, render phase, commit phase, and error recovery. Contains performConcurrentWorkOnRoot, performSyncWorkOnRoot, and the yield-to-host logic.
ReactFiberBeginWork.js — Render phase processing. For each fiber, determines what changed and constructs the work-in-progress tree. Handles all component types: function components, class components, host elements, portals, Suspense boundaries, fragments, profiler, and more.
ReactFiberHooks.js — All hook implementations. Maintains a linked list of hooks per fiber. The dispatcher pattern switches between mount, update, and re-render hook implementations. Key hooks: useState, useReducer, useEffect, useLayoutEffect, useRef, useMemo, useCallback, useContext, useTransition, useDeferredValue, useId, useSyncExternalStore, useActionState, useOptimistic.
ReactFiberCommitWork.js — Commit phase. Three sub-phases:
- Before mutation —
getSnapshotBeforeUpdate, ref detachment - Mutation — DOM insertions, updates, deletions
- Layout —
useLayoutEffect, ref attachment,componentDidMount/DidUpdate
ReactChildFiber.js — Child reconciliation algorithm. Implements the key-based diffing for lists, including the optimization for the common case of appending to the end.
ReactFiberLane.js — The lanes priority model. Each lane is a bit in a 31-bit integer. Lanes enable fine-grained priority control:
| Lane Group | Bit Range | Purpose |
|---|---|---|
| SyncLane | 0 | Discrete user events |
| InputContinuousLane | 1 | Continuous user events |
| DefaultLane | 4 | Normal priority updates |
| TransitionLanes | 5-20 | startTransition updates |
| RetryLanes | 21-25 | Suspense retries |
| IdleLane | 30 | Idle work |
| OffscreenLane | 31 | Activity (offscreen) |
ReactFiberConfig.js — Host config interface. Each renderer provides its own implementation (DOM, Native, Noop, Art, Test). The module is shimmed at build time via Rollup's module replacement.
Architecture Deep Dive: React Compiler
The compiler (compiler/packages/babel-plugin-react-compiler/src/) is a 7-phase pipeline that transforms React components into memoized equivalents:
Phase 1 — HIR Construction: HIR/BuildHIR.ts converts Babel AST into a High-level Intermediate Representation (control flow graph). Then SSA/EnterSSA.ts converts to Static Single Assignment form, and SSA/EliminateRedundantPhi.ts removes unnecessary phi nodes.
Phase 2 — Optimization: Optimization/ConstantPropagation.ts performs sparse conditional constant propagation. Optimization/DeadCodeElimination.ts removes unreferenced instructions.
Phase 3 — Type & Effect Inference: TypeInference/InferTypes.ts runs constraint-based type unification. Inference/AnalyseFunctions.ts analyzes nested function effects. Inference/InferMutationAliasingEffects.ts uses abstract interpretation to infer which values are mutated or aliased.
Phase 4 — Reactive Scope Construction: Groups co-mutating variables into reactive scopes that will become useMemo calls. Aligns scopes to block boundaries, merges overlapping scopes, and computes minimal dependencies.
Phase 5 — HIR to Reactive Function: ReactiveScopes/BuildReactiveFunction.ts converts the CFG into a tree structure.
Phase 6 — Reactive Function Optimization: Prunes non-escaping scopes, unused scopes, and non-reactive dependencies. Merges scopes that invalidate together.
Phase 7 — Code Generation: ReactiveScopes/CodegenReactiveFunction.ts generates the final Babel AST with memoization code.
Architecture Deep Dive: Flight Protocol (Server Components)
The Flight protocol enables streaming Server Components from server to client:
Server side (packages/react-server/src/): Renders the Server Component tree, serializing it as a custom streaming format. Components can be async. Client Components are serialized as references (module ID + export name). Props are serialized as JSON with support for special types (Date, Map, Set, FormData, typed arrays).
Client side (packages/react-client/src/): Deserializes the stream, resolving Client Component references using the bundler integration. Reconstructs the React element tree and passes it to the client renderer.
Bundler integrations provide the module reference system:
| Package | Bundler | Module Resolution |
|---|---|---|
react-server-dom-webpack |
Webpack | Module ID + chunk mapping |
react-server-dom-turbopack |
Turbopack | Module path-based references |
react-server-dom-parcel |
Parcel | Parcel module IDs |
react-server-dom-esm |
Native ESM | File path import specifiers |
react-server-dom-unbundled |
None | Node.js loader hooks |
Module Reference: Core Exports
packages/react/src/ReactClient.js exports:
| Export | Type | Description |
|---|---|---|
Children |
Utility | map, forEach, count, only, toArray for child elements |
Component |
Class | Base class with setState, forceUpdate |
PureComponent |
Class | Component with shallow prop/state comparison |
createElement |
Function | Create React elements (legacy, prefer JSX) |
cloneElement |
Function | Clone element with merged props |
createContext |
Function | Create context with Provider/Consumer |
createRef |
Function | Create ref object ({ current: null }) |
forwardRef |
Function | Forward refs through components |
lazy |
Function | Code-split with dynamic import |
memo |
Function | Memoize component by props |
isValidElement |
Function | Check if value is a React element |
use |
Hook | Read promises and contexts |
useState |
Hook | Local state |
useReducer |
Hook | Reducer-based state |
useEffect |
Hook | Post-render side effects |
useLayoutEffect |
Hook | Synchronous post-mutation effects |
useInsertionEffect |
Hook | Pre-mutation effects (CSS-in-JS) |
useContext |
Hook | Read context value |
useRef |
Hook | Mutable ref container |
useImperativeHandle |
Hook | Customize ref handle |
useMemo |
Hook | Memoize computation |
useCallback |
Hook | Memoize function |
useId |
Hook | Generate unique IDs |
useDebugValue |
Hook | DevTools label |
useSyncExternalStore |
Hook | External store subscription |
useDeferredValue |
Hook | Defer non-urgent updates |
useTransition |
Hook | Mark transitions |
useActionState |
Hook | Form action state management |
useOptimistic |
Hook | Optimistic UI updates |
useEffectEvent |
Hook | Stable event callbacks (experimental) |
startTransition |
Function | Start transition outside components |
cache |
Function | Cache async function results (experimental) |
Fragment |
Component | Group without DOM wrapper |
StrictMode |
Component | Development checks |
Suspense |
Component | Async loading boundaries |
Profiler |
Component | Performance measurement |
Activity |
Component | Visibility control (experimental) |
ViewTransition |
Component | View transition animations (experimental) |
addTransitionType |
Function | Annotate transitions (experimental) |
act |
Function | Testing utility (DEV only) |
captureOwnerStack |
Function | Capture component stack (DEV only) |
Code Patterns and Conventions
__DEV__ guards: All development-only code (warnings, validation, stack traces) is wrapped in if (__DEV__) { ... }. The build system replaces __DEV__ with true (development) or false (production), and dead code elimination removes the branches.
Feature flags: Runtime behavior variations use flags from packages/shared/ReactFeatureFlags.js. Flags are boolean constants that the build system may inline.
Fork pattern: Platform-specific code uses forks/ directories. The Rollup build replaces module imports with the correct fork based on the target renderer. Example: ReactFiberConfig.js is replaced with ReactFiberConfigDOM.js for react-dom.
Error codes: Production error messages are replaced with numeric codes. The mapping is in scripts/error-codes/codes.json. Development builds include the full message; production builds include a URL to look up the error.
Flow types: Core packages use Flow for type checking. Type annotations use Flow syntax (type Foo = { ... }, function bar(x: string): void). The compiler packages use TypeScript instead.
Shared internals: Cross-package communication uses __CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE (React) and __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE (ReactDOM). These are private APIs not intended for external use.
Testing Strategy
| Test Type | Framework | Location | Command |
|---|---|---|---|
| Unit tests | Jest | packages/*/src/__tests__/ |
yarn test |
| Integration tests | Jest | packages/react-dom/src/__tests__/ |
yarn test |
| Fixture tests | Manual/Automated | fixtures/ |
yarn test-dom-fixture |
| Snapshot tests | Jest | packages/*/src/__tests__/__snapshots__/ |
yarn test |
| Compiler snapshots | Custom (snap) |
compiler/packages/snap/ |
yarn snap |
| E2E (Compiler) | Playwright | compiler/apps/playground/__tests__/e2e/ |
yarn test (in compiler) |
| Build validation | Custom | scripts/rollup/validate/ |
yarn lint-build |
| Type checking | Flow / TypeScript | Project-wide | yarn flow / tsc |
Custom Jest environment files:
ReactDOMServerIntegrationEnvironment.js— Extends Node environment for SSR integration testsReactJSDOMEnvironment.js— Extends JSDOM environment with custom teardown
Custom Jest matchers and reporters:
scripts/jest/matchers/— Custom assertion helpersscripts/jest/spec-equivalence-reporter/— Reports spec equivalence across configurationsscripts/jest/sizeBalancedSequencer.js— Distributes tests across workers by size
Potential Improvements
Based on the codebase analysis, the following areas have room for improvement:
-
react-reconciler/src/size: At 81 files and 1.6M chars, the reconciler is exceptionally large. Some files (e.g.,ReactFiberBeginWork.js,ReactFiberHooks.js,ReactFiberCommitWork.js) are individually massive. Breaking these into smaller, focused modules would improve maintainability. -
Flow to TypeScript migration: Core packages still use Flow while the compiler uses TypeScript. A full migration would unify the type system and improve IDE support.
-
Test infrastructure complexity: The test setup involves custom Jest configs, environments, sequencers, and preprocessors across 25 files. This makes it difficult for new contributors to understand how to run and write tests.
-
DevTools bundle:
react-devtools-sharedalone is 20 files / 160K chars of source. The DevTools architecture could benefit from clearer separation between the fiber inspection backend and the UI frontend.
Contributing Guide
- Fork the repository and clone locally
- Install dependencies:
yarn install - Create a branch from
main - Make changes following existing code patterns
- Run tests:
yarn test - Run type checks:
yarn flow - Run linting:
yarn lint - Format code:
yarn prettier-all - Submit a pull request
Note
The repository uses Yarn 1.22.22 workspaces. Do not use npm or pnpm. The
postinstallscript generates Flow configs — runyarn installafter any dependency changes.
Custom ESLint rules (scripts/eslint-rules/):
no-production-logging— Preventsconsole.*calls outside__DEV__guardsno-for-of-loops— Bansfor...ofto avoid iterator overheadwarning-args— Validates warning/error function call signaturessafe-string-coercion— Prevents implicit string coercion of symbols/temporals
9. Integration Points
Bundler Integration
React provides different builds for different bundlers and environments:
| Entry Point | When to Use |
|---|---|
react/index.js |
Standard client-side |
react/react.react-server.js |
Server Component environment |
react/compiler-runtime.js |
React Compiler runtime |
react-dom/client.js |
Client rendering (createRoot, hydrateRoot) |
react-dom/server.node.js |
Node.js SSR |
react-dom/server.edge.js |
Edge runtime SSR |
react-dom/server.browser.js |
Browser-based SSR |
react-dom/server.bun.js |
Bun runtime SSR |
react-dom/static.js |
Static pre-rendering |
react-dom/profiling.js |
Profiling-enabled client build |
Custom Renderers
Build a custom renderer by implementing the host config interface and connecting it to the reconciler:
import Reconciler from 'react-reconciler';
const hostConfig = {
createInstance(type, props) { /* ... */ },
appendInitialChild(parent, child) { /* ... */ },
appendChild(parent, child) { /* ... */ },
removeChild(parent, child) { /* ... */ },
commitUpdate(instance, type, oldProps, newProps) { /* ... */ },
// ... ~60 methods total
};
const MyRenderer = Reconciler(hostConfig);
The react-noop-renderer (packages/react-noop-renderer/) serves as a reference implementation for custom renderers.
DevTools Integration
React DevTools communicates via a Bridge class (packages/react-devtools-shared/src/bridge.js) that abstracts the transport layer (WebSocket for standalone, window.postMessage for extensions).
The backend hooks into React's internal fiber tree via the __REACT_DEVTOOLS_GLOBAL_HOOK__ global that the extension injects before React loads.