Skip to main content

Contributing to React Compiler

Thank you for your interest in contributing to React Compiler! This guide will help you set up your development environment and understand the contribution workflow.

Getting Started

Prerequisites

  • Node.js: Version 18 or higher
  • Yarn: Package manager (v1 or v3+)
  • Git: For version control
  • Editor: VS Code recommended (with TypeScript support)

Clone the Repository

Install Dependencies

Build the Compiler

Development Workflow

Running Tests

React Compiler uses a custom test runner called snap:

Test Fixtures

Test fixtures are located in:
Fixture types:
  • feature-name.js - Normal test case
  • feature-name.expect.md - Expected output
  • error.todo-*.js - Known limitation (graceful bailout)
  • error.bug-*.js - Known bug
Fixture format:

Adding a New Test

  1. Create fixture file:
  1. Write test code:
my-feature.js
  1. Generate expected output:
  1. Verify output:

Compiling Arbitrary Files

Test the compiler on any file:

Minimizing Test Cases

Reduce a failing test to minimal reproduction:

Code Structure

Key Directories

Important Files

  • src/Entrypoint/Pipeline.ts - Main compilation pipeline
  • src/HIR/HIR.ts - HIR type definitions
  • src/HIR/Environment.ts - Configuration schema
  • src/CompilerError.ts - Error handling

Making Changes

Modifying a Pass

Before modifying a pass, read its documentation:
Each pass has detailed documentation explaining:
  • Purpose and invariants
  • Input/output guarantees
  • Algorithm description
  • Edge cases
Example workflow:
  1. Find the pass:
  1. Read the documentation:
  1. Locate the implementation:
  1. Make your changes
  2. Add test cases
  3. Run tests:

Adding a New Pass

  1. Create the pass file:
src/MyCategory/MyNewPass.ts
  1. Add to pipeline:
src/Entrypoint/Pipeline.ts
  1. Add documentation:
  1. Write tests:

Adding Configuration Options

  1. Update schema:
src/HIR/Environment.ts
  1. Use in code:
  1. Document in configuration.mdx

Error Handling

Error Types

When to Use Each

  • throwTodo: Known limitation, expected pattern that’s not yet supported
  • invariant: Unexpected state indicating a compiler bug
  • InvalidReact: User code violates React’s rules
  • InvalidJS: Syntactically invalid JavaScript

Debugging

Debug Output

Run tests with debug logging:
This shows HIR after each pass.

Custom Logger

Create a debug logger:

Breakpoints

Set breakpoints in VS Code:
  1. Open file in editor
  2. Click left of line number to add breakpoint
  3. Run test in debug mode: F5
Use pretty printer:

Submitting Changes

Commit Guidelines

React Compiler uses Sapling (similar to Mercurial):

Commit Message Format

Opening a Pull Request

  1. Push your changes:
  1. Create PR on GitHub:
  • Base: facebook/react:main
  • Title: Brief description
  • Description: Detailed explanation + test plan
  1. Address review feedback
  2. Wait for CI to pass

PR Checklist

  • Tests added for new functionality
  • All tests passing (yarn snap)
  • Pass documentation updated (if modifying pass)
  • Configuration documented (if adding options)
  • Examples added to fixtures
  • Commit message follows format
  • No unrelated changes

Code Style

TypeScript

  • Use explicit types for public APIs
  • Prefer interface over type for objects
  • Use const over let when possible
  • Avoid any - use unknown instead

Naming Conventions

  • Files: PascalCase for classes, camelCase for utilities
  • Variables: camelCase
  • Types: PascalCase
  • Constants: UPPER_SNAKE_CASE
  • Private fields: #privateField (private class fields)

Formatting

Code is automatically formatted. Run:

Getting Help

Resources

  • Documentation: Read docs/ and docs/passes/
  • CLAUDE.md: Compiler knowledge base
  • GitHub Issues: Search existing issues
  • Discord: React Compiler channel

Asking Questions

When asking for help, provide:
  1. What you’re trying to do
  2. What you’ve tried
  3. Minimal reproduction (test fixture)
  4. Expected vs actual behavior
  5. Error messages (full output)

Common Tasks

Update Expected Output

Run Specific Category

Check Type Errors

Run Linter

Build for Production

Advanced Topics

Custom Test Runner

The snap runner is in packages/snap/. It:
  • Discovers fixtures
  • Compiles code
  • Generates expected output
  • Executes code in both versions
  • Compares results

Compiler Profiling

Enable timing:

Memory Profiling

Use Node inspector:
Open Chrome DevTools and profile.

Best Practices

Writing Tests

  1. One concept per fixture - Each test should validate one behavior
  2. Descriptive names - Name clearly indicates what’s tested
  3. Comments - Explain why behavior is expected
  4. Edge cases - Test boundary conditions

Code Quality

  1. Keep passes focused - Each pass should do one thing well
  2. Document invariants - State assumptions clearly
  3. Error messages - Make them actionable
  4. Performance - Avoid O(n²) algorithms when possible

Review Process

  1. Self-review - Review your own changes first
  2. Test thoroughly - Run on real-world code
  3. Explain changes - Help reviewers understand
  4. Respond promptly - Address feedback quickly

Next Steps

Architecture

Understand the compiler pipeline

HIR

Learn the intermediate representation

Optimization Passes

Study specific passes

Configuration

Configuration options reference

License

By contributing to React Compiler, you agree that your contributions will be licensed under the MIT license.