Oxlint v1.71 and Oxfmt v0.56 Ship the v0.137 Crates Wins, Land 18 New Linter Rules, and Tame React Lifecycle Traversal with a Streamed-Iterator Refactor

Oxlint v1.71 and Oxfmt v0.56 Ship the v0.137 Crates Wins, Land 18 New Linter Rules, and Tame React Lifecycle Traversal with a Streamed-Iterator Refactor

lschvn

Oxlint v1.71.0 and oxfmt v0.56.0 shipped together on June 22, 2026, four days after the crates_v0.137.0 release and one week after the v1.70.0 apps release. The release is the apps-side pickup of the v0.137 crates cycle and the last apps release before the v0.138 crates line lands on Monday 2026-06-29. The headline work is the bucketed rule dispatch refactor on the linter side and the CRLF normalization + member-chain panic fix on the formatter side.

The Oxlint release carries 18 new features, 28 bug fixes, and 13 performance entries. The Oxfmt release carries 9 bug fixes and 3 performance entries. Total: 71 entries across the two apps, on par with the v1.70 cycle and slightly above the v1.68 cycle.

The headline: bucketed rule dispatch

The single largest performance change in v1.71 is linter: Reuse rule dispatch buckets (#23450, camc314), followed by linter: Use bucketed dispatch for all files (#23452, camc314). Before v1.71, the linter emitted one RuleEnum match arm per timing branch on every entry to a rule, then re-emitted the same match arms on every subsequent file. The bucketed refactor moves the match arms to a single allocation that is reused across all files in a run.

The complementary performance entry is linter: Emit RuleEnum dispatch match once instead of per timing branch (#23499, Boshen). Together, the two PRs remove the per-file setup cost that dominated oxlint's wall time on cold runs. The rule work itself was already fast; what was expensive was the bookkeeping around it.

The release also fixes the cold-start cost: oxlint: Start Tokio only for LSP (#23447, camc314) moves the Tokio async-runtime startup out of the CLI path. Before v1.71, oxlint started a Tokio runtime on every invocation, even when the CLI was running synchronously and never needed one. After v1.71, the LSP path still gets a runtime (it needs one to drive the language-server protocol), and the CLI path skips the startup cost entirely.

The v0.137 crates pickup

The v0.137 crates release on June 18 shipped two new minifier treeshaking passes, a long-running incremental scoping refresh that retired LiveUsageCollector, and two ESTree breaking changes. The v1.71 apps release picks up the user-visible parts: minifier: Treeshake pure typed arrays and Set/Map array literals (#23469, Dunqing) is in the v1.71 minifier build, along with LiveUsageCollector removal, the parser perf patches, and the React Compiler perf entries. The two breaking ESTree changes (#23574, #23573) are opt-in: they affect downstream crates that build a custom ESTree AST, not oxlint users.

The companion minifier pass inline const value for read-only vars (#22593) is also in the v1.71 minifier build. Both passes remain off by default; the minifier's CompressOptions defaults in v1.71 match v1.70 / v0.136, so the gains are opt-in via the config.

18 new linter rules

The v1.71 release ships 18 new linter rules across ESLint, TypeScript, Node, Unicorn, Vue, JSDoc, and React categories. The most consequential:

  • unicorn/prefer-number-coercion (#23497, Shekhu) catches the Number(x) vs +x vs parseFloat(x) consistency problem at lint time.
  • node/no-sync (#23589, fujitani sora) flags synchronous filesystem and child-process calls in server entrypoints.
  • vue/no-async-in-computed-properties (#23493, bab) closes a real correctness gap in Vue computed-property definitions.
  • node/no-mixed-requires (#23539, fujitani sora) flags mixed require styles in CommonJS modules.
  • unicorn/max-nested-calls (#23461, arieleli01212) catches overly nested function chains.

The release also ships schema support for eslint/no-restricted-properties (#23619, Sysix), node/callback-return (#23615, Sysix), import/extensions (#23557, WaterWhisperer), unicorn/numeric-separators-style (#23554, Mikhail Baev), eslint/prefer-destructuring (#23410, WaterWhisperer), and react/jsx-no-script-url (#23475, WaterWhisperer). The schema work enables migration paths from ESLint configs that were previously manual.

On the suggestion side, linter/typescript: Implement suggestion for no-unnecessary-type-constraint rule (#23646, Mikhail Baev) and linter/jsdoc/require-param-type: Implement fixer (#23513, camc314) add auto-fix support for two rules that previously only reported.

The React lifecycle refactor

The single largest source of allocation churn on React codebases with deeply nested components was the react/no-deprecated and react/jsx-no-undef traversal, which collected every ancestor of every JSX element into a Vec before doing any rule work. linter: Stream React lifecycle ancestors (#23445, camc314) replaces the Vec collection with a streaming iterator that walks the ancestor chain on demand.

Combined with linter: Avoid JSX fragment child collections (#23486, camc314) and linter/oxc/branches-sharing-code: Borrow shared branch suggestion text (#23484, camc314), v1.71 is the first release where the React-related linter rules are allocation-aware on the hot path. The three PRs together account for the bulk of the React-related performance work in the release.

28 lint bug fixes, mostly Yunfei He

The 28 lint bug fixes in v1.71 are dominated by Yunfei He's fixer-rewrite work. The pattern is the same across the fixes: the pre-v1.71 linter would rewrite a code construct using string concatenation, drop parentheses that the source had explicitly added, or paste a fragment into a position where it produced invalid syntax. The v1.71 fixes preserve parentheses (#23578, #23579), preserve operand source text (#23533), skip fixes on receivers that are not the expected type (#23518, #23520, #23527), and preserve import aliases (#23568).

The standout fix is the parseInt(_, spread) panic. linter/radix: Avoid panic on parseInt with a spread radix argument (#23623, Jerry Zhao) closes a real panic that triggered when parseInt(x, ...args) was called with a computed radix argument. The same fix was applied to two neighbouring rules in the same release: linter/prefer-numeric-literals (#23624, Jerry Zhao) and the linter/radix follow-up (#23626). Pre-v1.71, the linter panicked and crashed CI on codebases that used parseInt with computed radix arguments.

Other notable bug fixes: linter/prefer-query-selector: Use a compound selector for multiple classes (#23628, Jerry Zhao) fixes a correctness gap in prefer-query-selector where a multi-class selector was rewritten as a sequence of single-class selectors, breaking the semantic intent; linter: False positives with non *.setTimeout call in no-confusing-set-timeout (#23444, camc314) stops the rule from flagging calls to setTimeout that came from a renamed import; and linter/eslint/no-useless-assignment: Handle exceptional control-flow paths (#23544, camc314) closes a correctness gap where the rule missed assignments inside try/finally blocks.

The formatter changes

Oxfmt v0.56.0 ships three substantive changes. The first is CRLF normalization for suppressed text: formatter_json: Normalize CRLF for suppressed text (#23702, leaysgur) and formatter: Normalize CRLF for suppressed text (#23701, leaysgur) ensure that suppression comments like // @ts-ignore and // oxlint-disable-next-line keep their line endings when the formatter rewrites the surrounding code on a project that mixes CRLF and LF. The second is the member-chain panic fix: formatter: Member chain panic when tail is merged with comment in dev build (#23698, leaysgur) closes a panic in the dev build that triggered when the tail of a member chain was merged with a trailing comment. The third is formatter: Preserve parens with default export and type cast (#23697, leaysgur), which keeps parentheses around export default x as Y constructs that the formatter previously flattened.

The formatter perf entries are smaller but consistent: formatter: Avoid arena copy for already-lowercase bigint literals (#23534, Yunfei He), formatter: Avoid arena copy for borrowed numeric-literal text (#23512, Yunfei He), and formatter: Avoid arena copy for borrowed string-literal text (#23465, Yunfei He) all remove arena copies that the pre-v0.56 formatter performed on text that the formatter had already determined was safe to borrow.

What v1.71 does not change

The release does not change rule defaults, the parser surface, or the React Compiler's public API. The minifier's CompressOptions defaults match v1.70 / v0.136. The LSP server gains the Tokio startup fix but does not gain a new protocol feature. The next crates release on Monday 2026-06-29 (v0.138) will be the first to ship changes that are not in the v0.137 cycle; the v1.71 apps release closes out the cycle that started with crates_v0.135 on 2026-06-08 and runs through the v1.70 apps release on 2026-06-15.

The release is also the third to carry the Oxc team's emoji-headed sections (🚀 Features, 🐛 Bug Fixes, ⚡ Performance, 📚 Documentation) format, which Oxc v0.135 introduced. The pattern matches the Biome changelog format and the Vite 8 release notes, and makes it easier to scan a release for what matters to your code at a glance.

What to watch

Three follow-ups are likely in the next two to four weeks. The first is the crates_v0.138.0 release on Monday 2026-06-29, which will be the first crates release not in the v0.137 cycle. The second is the corresponding oxlint v1.72.0 and oxfmt v0.57.0 apps release on Monday 2026-07-06, which will pick up whatever the v0.138 crates line ships. The third is the continuation of camc314's bucketed-dispatch refactor: the v1.71 release laid the groundwork, but several rules still use the per-rule allocation pattern that v1.71 retired for the dispatch layer; expect more bucketing work in v1.72.

Frequently Asked Questions

Related articles

More coverage with overlapping topics and tags.

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
tooling

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

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.
Bun Integrates the React Compiler Directly Into Its Bundler, Roughly 20x Faster Than the Babel Plugin
tooling

Bun Integrates the React Compiler Directly Into Its Bundler, Roughly 20x Faster Than the Babel Plugin

PR #32504, merged into oven-sh/bun on June 20, 2026, turns the upstream React Compiler Rust port into a built-in `bun build` transform behind `--react-compiler` and `Bun.build({ reactCompiler: true })`. Bun ports the upstream `facebook/react` `compiler/crates/` workspace directly into a single `src/react_compiler/` crate (~62k LOC) instead of going through Babel, SWC, or Oxc, and on a large React codebase (around 860 components, 1400 memo slots) the compiler pass runs in 465 ms versus 9.15 s for the Babel plugin. The feature is experimental, off by default, and ships with `reactCompilerOutputMode` (client or ssr) and a `scripts/sync-react-compiler.sh` re-sync helper.
Astro 7.0.0-beta.6 Stabilizes Route Caching and Promotes JSX Whitespace Compression to Default
tooling

Astro 7.0.0-beta.6 Stabilizes Route Caching and Promotes JSX Whitespace Compression to Default

Astro 7.0.0-beta.6 (June 19, 2026) promotes the experimental route caching API to top-level stable, dropping the experimental.cache and experimental.routeRules flags in favor of a new top-level cache config and a cache helper. Beta.5 (June 18) made 'jsx' the default compressHTML mode, changing the rendered output of every site that relied on the legacy whitespace preservation. Beta.6 also pulls in @astrojs/markdown-satteri 0.3.1-beta.2.

Comments

Log in Log in to join the conversation.

No comments yet. Be the first to share your thoughts.