MetaMask / MetaMask/metamask-mobile
Ratchet React Compiler `panicThreshold` in non-prod builds: `critical_errors`, then `all_errors`
- Dominant language
- TypeScript
- Stars
- 3k
- Forks
- 1.7k
- Avg merge
- 1d 14h
- Merged PRs (30d)
- 669
Description
> **Performance audit finding** · Severity: **Medium (tooling/ratchet)** · Effort: Medium, then ongoing · Fix risk: Simple (non-prod builds only) · Test safety net: N/A (build gate)
> Owner: `@MetaMask/mobile-platform (suggested)`
> File: `babel.config.js:67`
> Depends on: #31500 (logger triage — provides the actionable-error list this ratchet burns down)
### What is this about?
`panicThreshold` controls when a React Compiler diagnostic fails the build instead of silently skipping the file. Mobile currently runs the implicit default (`'none'`): every diagnostic is a silent skip, so compiler coverage can regress without anyone noticing. The ratchet makes a *non-production* build progressively intolerant:
| Setting | Build fails on | Use |
|---|---|---|
| `'none'` (current/default) | never — failed files silently skipped | production, permanently |
| `'critical_errors'` | compiler-internal invariant violations | CI/debug gate, first target |
| `'all_errors'` | every diagnostic incl. unsupported syntax | CI/debug gate, end state |
The extension tracks the same ladder as MetaMask-planning#6552 (enable `critical_errors`, fix violations) and #6553 (`all_errors`); its enablement-run split (metamask-extension#38007: 31 actionable errors vs 7,024 unsupported of 7,308 files) shows the actionable set a ratchet has to clear is small once the `Todo` category is excluded.
### Scenario
N/A — build tooling.
### Design
N/A.
### Technical Details
1. Add an env-gated Babel config path (or CI job) that sets `panicThreshold: 'critical_errors'` in the `'react-compiler'` plugin options for non-production builds. Production stays `'none'` permanently — one un-compilable file must never block a release for an optional optimization.
2. Fix the actionable (non-`Todo`) errors surfaced by the #31500 logger until the `critical_errors` gate passes; promote the gate to required CI.
3. Repeat toward `'all_errors'`. What remains after that is the unsupported (`Todo`) set, re-diffed on compiler upgrades — `Todo`s that newly compile are free wins, new errors are regressions the gate now catches.
### Threat Modeling Framework
N/A — non-production build gate; no runtime change.
### Acceptance Criteria
- Non-prod build passes at `panicThreshold: 'critical_errors'` and the gate runs in CI.
- Follow-up ratchet to `'all_errors'` tracked, with the remaining actionable-error count trending to zero.
- Production builds verified unaffected (`'none'`).
### References
- Files: `babel.config.js:67`
- Depends on: #31500; coverage-debt sibling: #31501
- Extension counterparts: MetaMask-planning#6552, #6553; reference implementation metamask-extension#38007 (`--reactCompilerDebug={all|critical|none}`)
- Source: `mms-performance` skill, `mm-react-compiler-error-triage` (MetaMask/skills#49)
- Status: tooling proposal
Contributor guide
Research direction
Start at babel.config.js:67 and inspect the react-compiler plugin options and how non-production builds are selected. Use the #31500 logger output to identify actionable non-Todo errors, then verify the CI gate at critical_errors while keeping production at none. Done means non-prod CI passes at critical_errors, production is unaffected, and the all_errors follow-up is tracked.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- babel, react, react-native
- Domain
- build-system, ci-cd, mobile, tooling
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100