---
title: "Oxc v0.137 Teaches the Minifier to Treeshake Pure Typed Arrays and Set/Map Literals, Lands an Incremental Scoping Refresh, and Fixes a React Compiler Edge Case"
description: "Oxc release crates_v0.137.0, published on 2026-06-18, ships two new minifier passes (treeshake pure typed arrays and Set/Map array literals via #23469, and inline const values for read-only vars via #22593), a long-running incremental scoping refresh that retires the LiveUsageCollector collector entirely (#23197), a friendly parser error for adjacent JSX elements (#23378), a React Compiler bug fix for computed-key imports (#23586), and two breaking changes to the ESTree config API (#23573, #23574). The minifier pass list also gets a Proxy-aware object-introspection fix (#23483) and a new Map/WeakSet/WeakMap preservation rule for string arguments (#23470). v0.137 is the first crates release since v0.135 on 2026-06-08 and the second since Bun's native React Compiler integration landed on 2026-06-20."
date: 2026-06-22
image: "/images/heroes/2026-06-22--oxc-v0-137-react-compiler-treeshake-perf.png"
author: lschvn
tags: ["tooling", "performance"]
tldr:
  - "Oxc crates v0.137.0, published 2026-06-18, ships two new minifier treeshaking passes: 'treeshake pure typed arrays and Set/Map array literals' (#23469, Dunqing) and 'inline const value for read-only vars' (#22593, Dunqing). The second pass turns `const FOO = computeFoo()` plus later `FOO` references into the inlined value, which gives the rest of the minifier a chance to fold the result, and the first pass drops array literals of `Uint8Array`, `Map`, `Set`, and friends whose values are pure and unused."
  - "The minifier also gets a long-running incremental scoping refresh that retires the LiveUsageCollector collector entirely (#23197). Combined with the perf-only patches in the same release (pre-sized statement vecs in TS enum/namespace lowering, pre-sized JSX props vecs, single-pass template-literal inline checks, single-ternary-branch evaluation, fixed Semantic::stats node counts reused in mangler builds), v0.137 is one of the densest perf crates in the project to date."
  - "The release carries two breaking ESTree changes ('Make whether to include TS fields a runtime option' #23574 and 'ESTree config use methods not consts' #23573), a React Compiler fix for imports referenced only by a computed key (#23586) that lands the same week as Bun's native React Compiler integration, a friendly parser error for adjacent JSX elements, and a parser fix that treats a line comment after `:` as leading rather than trailing."
faq:
  - question: "What is the headline feature of Oxc crates v0.137.0?"
    answer: "Two new minifier treeshaking passes: 'treeshake pure typed arrays and Set/Map array literals' (#23469) and 'inline const value for read-only vars' (#22593). The pure-array pass drops array literals of `Uint8Array`, `Map`, `Set`, and friends whose contents are pure and unused, and the inline-const pass substitutes the value of read-only `const` bindings at use sites, which lets the rest of the minifier fold the result. Both are off by default; the default in oxc_minifier v0.137 is the same as v0.136, so the gains are opt-in via `CompressOptions`."
  - question: "What does the incremental scoping refresh change?"
    answer: "The LiveUsageCollector collector was the only structure in oxc_minifier that walked the whole scope tree on every minifier pass to figure out which symbols were still live. The incremental scoping refresh (#23197) splits that into per-statement updates and skips a full walk when nothing downstream has changed. The author Dunqing notes in the PR that the collector was the largest constant cost in large minifier runs, and deleting it removes the only pass in oxc_minifier that still ran in O(scope) on every entry to a function body. The perf wins are real but depend on input size; the change shows up most on minified bundles over a few hundred kilobytes."
  - question: "How does this release relate to the React Compiler?"
    answer: "Two of the eleven performance entries in the release are in `react_compiler`. The biggest is 'Borrow binding names in prefilter instead of allocating' (#23471, Yunfei He), which removes a `String` allocation per prefilter hit on a function declaration. The bug fix is 'Keep imports referenced only by a computed key' (#23586, Boshen), which fixes a real correctness gap in the React Compiler's import tracking. These land the same week as [Bun's native React Compiler integration](/articles/2026-06-21--bun-react-compiler-bundler-integration-20x) (PR #32504, merged 2026-06-20), and Bun's port pulls the upstream `facebook/react` Rust workspace directly rather than going through an Oxc adapter, so the Oxc changes still flow back to the upstream compiler."
  - question: "What are the ESTree breaking changes in v0.137?"
    answer: "Two: 'Make whether to include TS fields a runtime option' (#23574, overlookmotel) and 'ESTree config use methods not consts' (#23573, overlookmotel). The first moves the decision of whether the ESTree AST exposes TypeScript-specific fields (TS annotations, type parameters, TS-only nodes) from a build-time `Cargo` feature to a runtime option on the ESTree builder. The second replaces public `const` items on the `ESTree` config struct with methods, so the call sites change from `config.include_ts_fields` to `config.include_ts_fields()`. Both are real breaking changes for downstream crates that build a custom ESTree AST and have to update their config calls. The compiler itself is unchanged; the breaking changes only affect the optional ESTree compatibility layer."
  - question: "Does v0.137 speed up the parser?"
    answer: "Marginally. 'Reduce code bloat from verify_modifiers monomorphization' (#23576, Boshen) trims monomorphization bloat out of the parser hot path, and the related semantic/mangler/minifier fix in #23352 makes `Semantic::stats` return correct node counts that the mangler can reuse instead of recomputing. These are real wins on large inputs but they are not benchmarked in the release; the release body is closer to a patch list than a benchmark report. Users of the standalone `oxc_parser` crate are unlikely to see a measurable wall-time difference; users of `oxc_minifier` on large inputs are the ones who will see the gains, mostly from the LiveUsageCollector removal and the pre-sized vecs."
  - question: "Will oxlint 1.71 ship on these crates?"
    answer: "Oxlint and oxfmt apps follow a weekly cadence on Mondays and pull the latest `crates_v0.x` line at release time. v0.137 was published 2026-06-18 (Thursday), and the last apps release (oxlint v1.70.0 and oxfmt v0.55.0) shipped 2026-06-15, so the next apps release on 2026-06-22 should pick up the v0.137 perf wins in the parser, minifier, and React Compiler crates, plus the live-usage removal in `oxc_minifier`."
---

[Oxc release crates_v0.137.0](https://github.com/oxc-project/oxc/releases/tag/crates_v0.137.0), published on June 18, 2026, ships two new minifier treeshaking passes, a long-running incremental scoping refresh, a friendly parser error for adjacent JSX elements, and a React Compiler bug fix for computed-key imports. The release also carries two breaking changes to the ESTree config API and the densest perf patch list in the project so far: eleven performance entries across the parser, the minifier, the mangler, the transformer, and the React Compiler.

This is the first crates release since v0.135 on June 8 and the second since [Bun's native React Compiler integration](/articles/2026-06-21--bun-react-compiler-bundler-integration-20x) merged into `oven-sh/bun` on June 20. Bun's port pulls the upstream `facebook/react` Rust workspace directly, so the Oxc changes here still flow back to the upstream compiler through Meta's port and the `react_compiler_oxc` adapter that other bundlers are picking up.

## The headline: two new minifier treeshaking passes

The new pass that users will feel first is `treeshake pure typed arrays and Set/Map array literals` ([#23469](https://github.com/oxc-project/oxc/pull/23469), Dunqing). The pre-v0.137 minifier could already treeshake a `const x = [1, 2, 3]` whose contents were pure, but it stopped at the typed-array boundary: a `new Uint8Array([1, 2, 3])` whose bytes were unused stayed in the output, as did a `new Map([["a", 1], ["b", 2]])` whose entries were never read. The v0.137 pass recognizes those constructors, walks the inner array literal, and treats it the same way the regular array-literal pass does: pure + unused => drop.

The complement is `inline const value for read-only vars` ([#22593](https://github.com/oxc-project/oxc/pull/22593), also Dunqing). The pre-v0.137 minifier would only inline a `const` binding if the binding was used exactly once; v0.137 inlines the value at every use site when the binding is a `const` and the value is treated as read-only by the type-aware analysis. That gives the rest of the minifier (constant folding, conditionals, return-statement simplification) a chance to fold the result. The PR description walks through a worked example: a `const FOO = computeFoo()` followed by a downstream `if (FOO > 0)` collapses to the inlined comparison when `computeFoo` is a pure literal-returning arrow, and to a constant-condition branch when it is a pure constant-returning arrow.

Both passes are gated behind `CompressOptions` flags, off by default in v0.137. The release notes are explicit that the default `CompressOptions` in oxc_minifier v0.137 matches v0.136, so the gains are opt-in.

## The biggest perf change: incremental scoping refresh

The single largest perf change in v0.137 is `Incremental scoping refresh, delete LiveUsageCollector` ([#23197](https://github.com/oxc-project/oxc/pull/23197), Dunqing). `LiveUsageCollector` was the only structure in `oxc_minifier` that walked the full scope tree on every minifier pass to figure out which symbols were still in use. The incremental scoping refresh splits that into per-statement updates and skips the full walk when no downstream change invalidates the cache.

Dunqing's PR description is direct: `LiveUsageCollector` was the largest constant cost in large minifier runs, and the only pass in `oxc_minifier` that still ran in O(scope) on every entry to a function body. Removing it deletes the only minifier internal that needed the full scope tree on every entry, and the rest of the minifier can now use a cheaper per-statement refresh. The release notes do not include a number, but the related perf patches in the same release tell the same story:

- `Mangler: compile slot sort once instead of per CAPACITY` ([#23577](https://github.com/oxc-project/oxc/pull/23577), Boshen)
- `Parser: reduce code bloat from verify_modifiers monomorphization` ([#23576](https://github.com/oxc-project/oxc/pull/23576), Boshen)
- `ESTree: remove pointless mem::take` ([#23572](https://github.com/oxc-project/oxc/pull/23572), overlookmotel)
- `Transformer: pre-size statement vecs in TS enum & namespace lowering` ([#23516](https://github.com/oxc-project/oxc/pull/23516), Yunfei He)
- `Minifier: compute template-literal inline checks in a single pass` ([#23467](https://github.com/oxc-project/oxc/pull/23467), Yunfei He)
- `Semantic, mangler, minifier: fix Semantic::stats node count and reuse stats in mangler builds` ([#23352](https://github.com/oxc-project/oxc/pull/23352), Boshen)
- `Minifier: evaluate ternary branches once in minimize_conditional_expression` ([#23479](https://github.com/oxc-project/oxc/pull/23479), Yunfei He)
- `Transformer: pre-size JSX props vec to attribute count` ([#23466](https://github.com/oxc-project/oxc/pull/23466), Yunfei He)
- `React Compiler: borrow binding names in prefilter instead of allocating` ([#23471](https://github.com/oxc-project/oxc/pull/23471), Yunfei He)

The semantic/mangler/minifier fix in #23352 is the one that the other perf entries build on: `Semantic::stats` previously returned node counts that did not match what the mangler was about to compute, so the mangler had to redo the work. The fix makes the counts match, and the rest of the release can reuse them. v0.137 is the first release where the semantic/mangler/minifier pipeline is consistent about stats.

## Two breaking changes to the ESTree config

The two breaking changes are both in the optional ESTree compatibility layer, not the compiler itself. `Make whether to include TS fields a runtime option` ([#23574](https://github.com/oxc-project/oxc/pull/23574), overlookmotel) moves the decision of whether the ESTree AST exposes TypeScript-specific fields (TS annotations, type parameters, TS-only nodes) from a `Cargo` build feature to a runtime option on the ESTree builder. `ESTree config use methods not consts` ([#23573](https://github.com/oxc-project/oxc/pull/23573), overlookmotel) replaces public `const` items on the `ESTree` config struct with methods, so call sites change from `config.include_ts_fields` to `config.include_ts_fields()`.

Downstream crates that build a custom ESTree AST have to update their config calls. The compiler itself, the parser, the transformer, the minifier, and the React Compiler are all unchanged by the ESTree rework. The ESTree layer is the one that lets Oxc emit an AST that matches the [ESTree spec](https://github.com/estree/estree), which is what tools like Rollup, esbuild, and webpack's `acorn`-based loader chain consume.

## The React Compiler entries

The two React Compiler entries are the most relevant to the previous day's news. `Keep imports referenced only by a computed key` ([#23586](https://github.com/oxc-project/oxc/pull/23586), Boshen) fixes a real correctness gap in the React Compiler's import tracking: an import whose only use is as the right-hand side of a computed key (for example, `obj[SomeImport]` where `SomeImport` is a renamed default import) was being dropped, which compiled away to undefined behaviour in the React Compiler's HIR. The fix keeps the import alive whenever a computed key resolves to it.

`Borrow binding names in prefilter instead of allocating` ([#23471](https://github.com/oxc-project/oxc/pull/23471), Yunfei He) is a perf entry, not a fix. The prefilter is the React Compiler's first pass over a function body to decide whether the body is a candidate for compilation; the prefilter used to allocate a `String` per hit, which on a large React codebase with many components adds up. The borrow removes the allocation.

These changes go into the upstream `facebook/react` Rust workspace, not just the Oxc fork. Bun's [native React Compiler integration](/articles/2026-06-21--bun-react-compiler-bundler-integration-20x) ports the upstream `compiler/crates/` workspace directly, so the v0.137 React Compiler entries will be in the next Bun sync. Oxlint and oxfmt pull the latest crates on their weekly release cadence, and the [oxlint 1.70 release](/articles/2026-06-12--oxc-v0-135-react-compiler-ast-breaking) two weeks ago was the first to ship the upstream port of the React Compiler as a Rust crate; v0.137 is the second crates release to carry React Compiler perf and correctness work.

## The parser UX work

Two parser changes are aimed at developer ergonomics rather than raw perf. `Parser: add friendly error for adjacent JSX elements` ([#23378](https://github.com/oxc-project/oxc/pull/23378), sapphi-red) replaces the cryptic "unexpected token" error that the parser used to emit when two adjacent JSX elements (e.g. `<a /><b />` at the start of a file without an explicit fragment wrapper) failed to parse, with a message that names the problem and points at the offending token. `Parser: treat a line comment after ':' as leading, not trailing` ([#23515](https://github.com/oxc-project/oxc/pull/23515), Dunqing) fixes a long-standing comment-attribution bug where a `// foo` comment after a `:` was attached to the previous token instead of the next one, which made source maps wrong in some cases.

## Two minifier correctness fixes worth calling out

The two minifier bug fixes are small but the kind of thing that bites in production:

- `Minifier: keep Object introspection calls on a possible Proxy` ([#23483](https://github.com/oxc-project/oxc/pull/23483), Dunqing) stops the minifier from dropping `Object.keys(obj)`, `Object.values(obj)`, `Object.entries(obj)`, and `Object.getOwnPropertyDescriptor(obj, key)` when `obj` could be a `Proxy`, because the call could invoke the proxy's `ownKeys` or `getOwnPropertyDescriptor` trap and return arbitrary values.
- `Minifier: keep new Map/WeakSet/WeakMap with a string argument` ([#23470](https://github.com/oxc-project/oxc/pull/23470), Dunqing) stops the minifier from dropping a `new Map([["a", 1]])` whose literal argument is a string-keyed array of pure entries, because the constructor's iteration order matters and the minifier was treating it as a no-op.

Both are in the same family as the new `treeshake pure typed arrays` pass, but in reverse: the new pass is an opt-in expansion of what the minifier can prove is safe to drop, and the two fixes are corrections to places where the pre-v0.137 minifier was over-aggressive.

## What v0.137 does not change

The release does not change the parser or minifier defaults, the transformer surface, or the React Compiler's public API. The breaking changes are confined to the optional ESTree config layer. The `oxc_ast`, `oxc_parser`, `oxc_semantic`, `oxc_transformer`, `oxc_minifier`, `oxc_mangler`, and `oxc_react_compiler` crate APIs are all backwards-compatible with v0.136. The next [oxlint and oxfmt apps release](https://github.com/oxc-project/oxc/releases) on the weekly Monday cadence will pick up the v0.137 perf wins in the parser, minifier, and React Compiler crates, plus the `LiveUsageCollector` removal in `oxc_minifier`.

The release is also the second to carry the Oxc team's new convention of breaking the body into emoji-headed sections (`💥 BREAKING CHANGES`, `🚀 Features`, `🐛 Bug Fixes`, `⚡ Performance`, `📚 Documentation`), which [Oxc v0.135](/articles/2026-06-12--oxc-v0-135-react-compiler-ast-breaking) introduced. The pattern matches the [Biome changelog format](https://github.com/biomejs/biome/releases) and the [Vite 8 release notes](/articles/2026-04-08--vite-8-stable-seven-patches-in-three-weeks), and makes it easier to scan a release for what matters to your code at a glance.
