refactor(napi/transform)!: remove the React Compiler option#23590
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 462093aafb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
462093a to
a3e801b
Compare
Merge activity
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a3e801bd95
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
## Summary Puts `oxc_react_compiler` behind a new `react_compiler` cargo feature in the `oxc-transform` napi binding, **off by default** — mirroring the existing `allocator` feature. Previously it was an unconditional dependency. - A plain `cargo build` / `napi build` (e.g. local dev, `build-dev`) drops the heavy `oxc_react_compiler` dependency entirely. - The npm `build` (publish) and `build-test` (CI) scripts opt in via `--features`, so the **published binding and CI tests keep React Compiler support** — no change to what npm users get. ## Why the JS option types stay (and `.d.ts` doesn't change) napi-derive can't reliably `#[cfg]` an individual `#[napi(object)]` field — it generates constructor code referencing the field even after `cfg` strips it. So rather than duplicate the whole `TransformOptions` struct, only the bridge into the heavy crate is gated: - The thin JS-facing types (`ReactCompilerOptions`, the `reactCompiler` field) are kept unconditionally, so `index.d.ts` / `index.js` are byte-identical with or without the feature and CI's `git diff --exit-code` stays green. - `resolve()` / `into_plugin_options()` and the one struct-literal line that sets `oxc::transformer::TransformOptions.react_compiler` are gated on the feature. Without the feature, the `reactCompiler` option remains in the type surface but is ignored at runtime (documented in the Cargo.toml feature comment). ## Build wiring - `Cargo.toml`: `default = []`; `react_compiler = ["dep:oxc_react_compiler", "oxc/react_compiler"]`; `oxc_react_compiler` is now `optional`, and `oxc` no longer force-enables its `react_compiler` feature. - `package.json`: `build` → `--features allocator,react_compiler`; `build-test` → `--features react_compiler`. The release workflow builds every published target (incl. wasm) through `build`, so all published binaries keep it. ## Verification - `cargo check` + `cargo clippy --all-targets`: clean for default (lean), `--features react_compiler`, and `--features allocator,react_compiler`. - `cargo tree -i oxc_react_compiler`: absent by default; present with the feature (dependency fully dropped when off). - `pnpm build-test` (the CI command, now `--features react_compiler`): builds; regenerated `index.d.ts` / `index.js` unchanged. - Publish form `napi build --features allocator,react_compiler` parses and activates both features. - `reactCompiler.test.ts`: 9/9 pass. - `Cargo.lock` unchanged. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
a3e801b to
f37153d
Compare
f37153d to
94d8159
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 94d8159816
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Merging this PR will not alter performance
Comparing Footnotes
|
Feature-gating React Compiler in the binding isn't workable: the generated `index.d.ts` either advertises a `reactCompiler` option that a default build ignores, or - if the type surface is gated too - stops matching the checked-in `.d.ts` once CI's `build-test` enables the feature. Remove it from `oxc-transform` entirely: drop the `reactCompiler` option, the `ReactCompilerOptions` / `ReactCompilerGating` / `ReactCompilerDynamicGating` types, the `oxc_react_compiler` dependency, and the React Compiler test. The Rust `oxc_transformer` crate keeps React Compiler behind its own feature; only the napi binding loses it. The `TransformOptions` conversion uses `..Default::default()` so it still compiles when a workspace build (e.g. `--all-features`) turns on `oxc_transformer`'s gated `react_compiler` field via Cargo feature unification. BREAKING CHANGE: `oxc-transform` no longer accepts the `reactCompiler` transform option (shipped in 0.135.0 and 0.136.0).
94d8159 to
5fc0448
Compare
|
any further context on when React Compiler might be added back to the napi binding? I'm experimenting with an incremental adoption of oxc via the oxc-loader webpack plugin, and it seems to use the napi. Is there a tracking issue? |
## Summary Removes React Compiler from the `oxc-transform` napi binding entirely. It was previously exposed as a `reactCompiler` transform option (added in #22942, shipped in 0.135.0 / 0.136.0). **Why not feature-gate it instead?** Gating React Compiler in the binding can't produce a consistent `index.d.ts`: - Keep the option types unconditionally → the published `.d.ts` advertises a `reactCompiler` option that a default (feature-off) build silently ignores. - Gate the type surface too → CI's `build-test` (which would enable the feature) regenerates a `.d.ts` that no longer matches the checked-in lean one, breaking `git diff --exit-code`. Removing it from the binding sidesteps both. React Compiler stays available to the Rust `oxc_transformer` crate behind its own `react_compiler` feature — only the napi binding loses it. ## Changes - Drop the `reactCompiler` option and the `ReactCompilerOptions` / `ReactCompilerGating` / `ReactCompilerDynamicGating` types. - Remove the `oxc_react_compiler` dependency and stop enabling `oxc`'s `react_compiler` feature. - Delete `src/react_compiler.rs` and `test/reactCompiler.test.ts`. - Regenerate `index.d.ts` (drops the three interfaces + the field; `index.js` is unchanged — they were type-only). ## Breaking change `oxc-transform` no longer accepts the `reactCompiler` option. It shipped in 0.135.0 and 0.136.0. ## Verification - `cargo check` + `cargo clippy --all-targets`: clean. - `cargo shear`: no issues; `Cargo.lock` drops only the `oxc_transform_napi → oxc_react_compiler` edge. - No remaining `reactCompiler` / `ReactCompilerOptions` references anywhere else in the repo. - `pnpm build-test` + `pnpm test`: 53/53 pass (the React Compiler test is removed). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…C (Rust React Compiler)
Replace the existing webpack transpilation pipeline with a three-pass setup
that uses OXC's native Rust React Compiler and eliminates most of the Babel
transform work.
New pipeline (webpack use[] runs right-to-left):
Pass 1 fullstory-annotation-loader — parse-only JSX annotation; OXC sees
annotated JSX and runs React Compiler before its own JSX transform.
Pass 2 oxc-react-compiler-loader — React Compiler + JSX + TypeScript +
env target in a single Rust pass (oxc-transform 0.136.0, pinned via
package.json overrides; NAPI binding removed in 0.137.0, see
oxc-project/oxc#23590 — re-exposure in progress).
Pass 3 babel-loader (worklets only) — react-native-worklets/plugin only;
no presets needed since OXC already handled types and JSX.
Included node_modules (Rule B) skip the React Compiler but still go through
OXC for JSX/TS transforms. Split into B1 (.ts/.tsx) and B2 (.js/.jsx) to
avoid upgrading .ts generic syntax to TSX lang.
Removed devDependencies superseded by OXC:
@babel/preset-react, @babel/preset-typescript,
@babel/preset-env, @babel/preset-flow, babel-plugin-react-native-web,
@babel/plugin-proposal-export-namespace-from, @babel/plugin-transform-class-properties
Retained (still used by Metro/babel-jest):
babel-plugin-react-compiler, @babel/plugin-proposal-class-properties,
@babel/plugin-transform-export-namespace-from
Build timing (clean / warm-cache):
Baseline (all-Babel): 186.5s / 187.9s
Previous (oxc-loader + Babel): 175.4s / 174.8s
This commit (OXC React Compiler): 71.4s / 71.8s — 62% faster than baseline
Co-authored-by: Cursor <[email protected]>
Exposes the React Compiler as a Cargo feature on the `oxc` crate and the `oxc-transform` napi binding. `oxc` already had a `react_compiler` feature, but nothing re-exported `oxc_react_compiler`, so enabling it produced a `TransformOptions::react_compiler` field whose `PluginOptions` type callers could not name. Add `oxc::react_compiler`, which also lets the binding build `PluginOptions` through `oxc` instead of depending on the crate directly. Restore the napi `reactCompiler` option, removed in #23590. That change rejected feature-gating because both options it saw were unworkable: unconditional types mean a feature-off build silently ignores the option, and gated types mean `build-test` regenerates a `.d.ts` that no longer matches the checked-in one. Gating below the type surface avoids both -- the JS-facing option types are plain strings and bools, so they stay unconditional and only the conversion into `PluginOptions` is gated. A `--no-default-features` build regenerates a byte-identical `index.d.ts`, and passing `reactCompiler` to such a build is a hard error rather than a silent no-op. The feature is on by default so the published binary supports what the types advertise. It is a default rather than `--features react_compiler` in the build scripts because `build` already passes `--features allocator`, and the napi CLI forwards repeated flags as `--features react_compiler allocator`, which cargo misreads. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Exposes the React Compiler as a Cargo feature on the `oxc` crate and the `oxc-transform` napi binding. `oxc` already had a `react_compiler` feature, but nothing re-exported `oxc_react_compiler`, so enabling it produced a `TransformOptions::react_compiler` field whose `PluginOptions` type callers could not name. Add `oxc::react_compiler`, which also lets the binding build `PluginOptions` through `oxc` instead of depending on the crate directly. Restore the napi `reactCompiler` option, removed in #23590. That change rejected feature-gating because both options it saw were unworkable: unconditional types mean a feature-off build silently ignores the option, and gated types mean `build-test` regenerates a `.d.ts` that no longer matches the checked-in one. Gating below the type surface avoids both -- the JS-facing option types are plain strings and bools, so they stay unconditional and only the conversion into `PluginOptions` is gated. A `--no-default-features` build regenerates a byte-identical `index.d.ts`, and passing `reactCompiler` to such a build is a hard error rather than a silent no-op. The feature is on by default so the published binary supports what the types advertise. It is a default rather than `--features react_compiler` in the build scripts because `build` already passes `--features allocator`, and the napi CLI forwards repeated flags as `--features react_compiler allocator`, which cargo misreads. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Summary
Removes React Compiler from the
oxc-transformnapi binding entirely. It was previously exposed as areactCompilertransform option (added in #22942, shipped in 0.135.0 / 0.136.0).Why not feature-gate it instead? Gating React Compiler in the binding can't produce a consistent
index.d.ts:.d.tsadvertises areactCompileroption that a default (feature-off) build silently ignores.build-test(which would enable the feature) regenerates a.d.tsthat no longer matches the checked-in lean one, breakinggit diff --exit-code.Removing it from the binding sidesteps both. React Compiler stays available to the Rust
oxc_transformercrate behind its ownreact_compilerfeature — only the napi binding loses it.Changes
reactCompileroption and theReactCompilerOptions/ReactCompilerGating/ReactCompilerDynamicGatingtypes.oxc_react_compilerdependency and stop enablingoxc'sreact_compilerfeature.src/react_compiler.rsandtest/reactCompiler.test.ts.index.d.ts(drops the three interfaces + the field;index.jsis unchanged — they were type-only).Breaking change
oxc-transformno longer accepts thereactCompileroption. It shipped in 0.135.0 and 0.136.0.Verification
cargo check+cargo clippy --all-targets: clean.cargo shear: no issues;Cargo.lockdrops only theoxc_transform_napi → oxc_react_compileredge.reactCompiler/ReactCompilerOptionsreferences anywhere else in the repo.pnpm build-test+pnpm test: 53/53 pass (the React Compiler test is removed).🤖 Generated with Claude Code