---
title: "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"
description: "Oxlint apps_v1.71.0 and oxfmt apps_v0.56.0, both published on 2026-06-22, close out the v0.137 crates cycle. Oxlint v1.71 picks up the new treeshaking pure typed arrays minifier pass (#23469), the prefer-query-selector compound selector fix, 28 lint bug fixes (most of them Yunfei He's fixer-rewrite work), 13 performance entries anchored on a bucketed rule dispatch refactor (#23450, #23452, #23482-#23486, #23489, #23492), and the oxlint Tokio-on-LSP-only startup (#23447). Oxfmt v0.56.0 ships 9 bug fixes (CRLF normalization for `// @ts-ignore` suppressed text in #23701 and #23702, the member-chain panic fix #23698, the default-export-with-type-cast preservation #23697) and 3 formatter performance entries that remove arena copies on bigint, numeric-literal, and string-literal text. v1.71 is the first apps release since v1.70.0 on 2026-06-15, and the last one before the v0.138 crates release that will land on Monday 2026-06-29."
date: 2026-06-23
image: "/images/heroes/2026-06-23--oxlint-v1-71-oxfmt-v0-56.png"
author: lschvn
tags: ["tooling", "performance"]
tldr:
  - "Oxlint v1.71.0 and oxfmt v0.56.0, both published 2026-06-22, close out the v0.137 crates cycle on the apps side. Oxlint picks up the `treeshake pure typed arrays and Set/Map array literals` minifier pass (#23469, Dunqing) that the [v0.137 crates release](/articles/2026-06-22--oxc-v0-137-react-compiler-treeshake-perf) shipped but the apps release did not, plus the new `no-restricted-globals` upstream options (#23663), `node/no-sync` (#23589), `unicorn/prefer-number-coercion` (#23497), and `vue/no-async-in-computed-properties` (#23493)."
  - "The performance side is dominated by a bucketed rule dispatch refactor (#23450, #23452, camc314): the linter now reuses rule-dispatch buckets and `RuleEnum` match arms across files instead of emitting one match arm per timing branch (#23499, Boshen), avoids temporary `Vec` allocations in `typescript/no-unnecessary-parameter-property-assignment` (#23492) and `eslint/no-useless-switch-case` (#23489), borrows shared branch-suggestion text in `oxc/branches-sharing-code` (#23484), and skips JSX fragment child collections (#23486). The release also fixes the cold-start cost of oxlint: `oxlint: Start Tokio only for LSP` (#23447) keeps the async runtime dormant on the CLI path."
  - "Oxfmt v0.56.0 normalizes CRLF for suppressed text in both the JSON formatter (#23702) and the JS/TS formatter (#23701), fixes the member-chain panic when the tail merges with a comment in a dev build (#23698), and ships three formatter perf entries that avoid arena copies for already-lowercase bigint literals (#23534), borrowed numeric-literal text (#23512), and borrowed string-literal text (#23465). The 28 lint bug fixes are mostly Yunfei He's fixer-rewrite work; the standout is the `parseInt(_, spread)` panic fix in three rules at once (#23623, #23624, #23626)."
faq:
  - question: "What is the headline change in oxlint v1.71.0?"
    answer: "The headline is the bucketed rule dispatch refactor (#23450, #23452, camc314): the linter now reuses rule-dispatch buckets and `RuleEnum` match arms across files instead of emitting one match arm per timing branch (#23499, Boshen). On a real-world monorepo with several thousand files, the refactor removes the per-file setup cost that dominated oxlint's wall time on cold runs; the rule work itself was already fast. The cold-start path also gets the `oxlint: Start Tokio only for LSP` fix (#23447), so the CLI no longer pays the Tokio startup cost when it does not need it."
  - question: "Does oxlint v1.71 ship the new minifier treeshaking passes from crates v0.137?"
    answer: "Yes. `treeshake pure typed arrays and Set/Map array literals` (#23469, Dunqing) lands in oxlint v1.71.0; it is the apps-side pickup of the same PR that the [crates v0.137 release](/articles/2026-06-22--oxc-v0-137-react-compiler-treeshake-perf) shipped four days earlier. The companion pass `inline const value for read-only vars` (#22593) is also in the v1.71 minifier build. Both passes are off by default; the minifier's `CompressOptions` defaults match v0.136 / v1.70, so the gains are opt-in via the config."
  - question: "Which new linter rules are the most consequential?"
    answer: "Three land at the top of the consequential list: `unicorn/prefer-number-coercion` (#23497, Shekhu), which catches the `Number(x)` vs `+x` vs `parseFloat(x)` consistency problem at lint time; `node/no-sync` (#23589, fujitani sora), which flags synchronous filesystem and child-process calls in server entrypoints; and `vue/no-async-in-computed-properties` (#23493, bab), which closes a real correctness gap in Vue computed-property definitions. The `eslint/no-restricted-properties` schema (#23619) and the `unicorn/numeric-separators-style` option support (#23524, #23554) are also notable because they enable migration paths from ESLint configs that were previously manual."
  - question: "What does the oxlint Tokio-on-LSP-only change do?"
    answer: "`oxlint: Start Tokio only for LSP` (#23447, camc314) moves the Tokio async-runtime startup out of the CLI path and into the LSP 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 fix is small on warm runs but visible on cold runs in CI, where the saved Tokio startup compounds with the bucketed dispatch refactor to give the v1.71 CLI a measurable wall-time improvement on large codebases."
  - question: "What is the React lifecycle refactor in v1.71?"
    answer: "`linter: Stream React lifecycle ancestors` (#23545, camc314) replaces the previous `react/no-deprecated` and `react/jsx-no-undef` traversal, which collected every ancestor of every JSX element into a `Vec`, with a streaming iterator that walks the ancestor chain on demand. The refactor is the single largest source of allocation churn on React codebases with deeply nested components. Combined with `Avoid JSX fragment child collections` (#23486) and `Borrow shared branch suggestion text` in `oxc/branches-sharing-code` (#23484), v1.71 is the first release where the React-related linter rules are allocation-aware on the hot path."
  - question: "Are there breaking changes in oxlint v1.71?"
    answer: "No breaking rule removals. The release does tighten a few fixer behaviours: `linter/curly: Remove only the block's own braces` (#23580) stops the `curly` rule from removing braces that belong to a parent block when the inner block has none, `linter/no-compare-neg-zero: Delete the - of a parenthesized -0` (#23578) preserves parentheses around `-0` comparisons, and `linter/array-type: Parenthesize a conditional-type element` (#23579) is a formatter-side parity fix. None of these change rule defaults, but they can affect fixer output on codebases that previously relied on the old (incorrect) behaviour."
  - question: "What changes in oxfmt v0.56.0?"
    answer: "Three substantive changes. First, CRLF normalization for suppressed text: `formatter_json: Normalize CRLF for suppressed text` (#23702) and `formatter: Normalize CRLF for suppressed text` (#23701) 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. Second, the `formatter: Member chain panic when tail is merged with comment in dev build` fix (#23698) closes a real panic in the dev build that triggered when the tail of a member chain was merged with a trailing comment. Third, `formatter: Preserve parens with default export and type cast` (#23697) keeps parentheses around `export default x as Y` constructs that the formatter previously flattened."
  - question: "Why is the `parseInt(_, spread)` panic fix worth calling out?"
    answer: "The fix is `linter/radix: Avoid panic on parseInt with a spread radix argument` (#23623, Jerry Zhao), and the same fix was applied to two neighbouring rules in the same release: `linter/prefer-numeric-literals` (#23624) and the `linter/radix` follow-up (#23626). The pre-v1.71 linter panicked on `parseInt(x, ...args)` because the radix argument's runtime type was not known and the rule assumed a literal. The fix recognises the spread, defers the radix check, and reports the rule without a panic. The fix matters because panics in a linter are loud failures; the previous behaviour would crash CI on codebases that used `parseInt` with computed radix arguments."
---

[Oxlint v1.71.0](https://github.com/oxc-project/oxc/releases/tag/apps_v1.71.0) and [oxfmt v0.56.0](https://github.com/oxc-project/oxc/releases/tag/apps_v1.71.0) shipped together on June 22, 2026, four days after the [crates_v0.137.0 release](/articles/2026-06-22--oxc-v0-137-react-compiler-treeshake-perf) and one week after the [v1.70.0 apps release](/articles/2026-06-12--oxc-v0-135-react-compiler-ast-breaking). 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](https://github.com/oxc-project/oxc/pull/23450), camc314), followed by `linter: Use bucketed dispatch for all files` ([#23452](https://github.com/oxc-project/oxc/pull/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](https://github.com/oxc-project/oxc/pull/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](https://github.com/oxc-project/oxc/pull/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](https://github.com/oxc-project/oxc/pull/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](https://github.com/oxc-project/oxc/pull/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](https://github.com/oxc-project/oxc/pull/23497), Shekhu) catches the `Number(x)` vs `+x` vs `parseFloat(x)` consistency problem at lint time.
- `node/no-sync` ([#23589](https://github.com/oxc-project/oxc/pull/23589), fujitani sora) flags synchronous filesystem and child-process calls in server entrypoints.
- `vue/no-async-in-computed-properties` ([#23493](https://github.com/oxc-project/oxc/pull/23493), bab) closes a real correctness gap in Vue computed-property definitions.
- `node/no-mixed-requires` ([#23539](https://github.com/oxc-project/oxc/pull/23539), fujitani sora) flags mixed require styles in CommonJS modules.
- `unicorn/max-nested-calls` ([#23461](https://github.com/oxc-project/oxc/pull/23461), arieleli01212) catches overly nested function chains.

The release also ships schema support for `eslint/no-restricted-properties` ([#23619](https://github.com/oxc-project/oxc/pull/23619), Sysix), `node/callback-return` ([#23615](https://github.com/oxc-project/oxc/pull/23615), Sysix), `import/extensions` ([#23557](https://github.com/oxc-project/oxc/pull/23557), WaterWhisperer), `unicorn/numeric-separators-style` ([#23554](https://github.com/oxc-project/oxc/pull/23554), Mikhail Baev), `eslint/prefer-destructuring` ([#23410](https://github.com/oxc-project/oxc/pull/23410), WaterWhisperer), and `react/jsx-no-script-url` ([#23475](https://github.com/oxc-project/oxc/pull/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](https://github.com/oxc-project/oxc/pull/23646), Mikhail Baev) and `linter/jsdoc/require-param-type: Implement fixer` ([#23513](https://github.com/oxc-project/oxc/pull/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](https://github.com/oxc-project/oxc/pull/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](https://github.com/oxc-project/oxc/pull/23486), camc314) and `linter/oxc/branches-sharing-code: Borrow shared branch suggestion text` ([#23484](https://github.com/oxc-project/oxc/pull/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](https://github.com/oxc-project/oxc/pull/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](https://github.com/oxc-project/oxc/pull/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](https://github.com/oxc-project/oxc/pull/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](https://github.com/oxc-project/oxc/pull/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](https://github.com/oxc-project/oxc/pull/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](https://github.com/oxc-project/oxc/pull/23702), leaysgur) and `formatter: Normalize CRLF for suppressed text` ([#23701](https://github.com/oxc-project/oxc/pull/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](https://github.com/oxc-project/oxc/pull/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](https://github.com/oxc-project/oxc/pull/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](https://github.com/oxc-project/oxc/pull/23534), Yunfei He), `formatter: Avoid arena copy for borrowed numeric-literal text` ([#23512](https://github.com/oxc-project/oxc/pull/23512), Yunfei He), and `formatter: Avoid arena copy for borrowed string-literal text` ([#23465](https://github.com/oxc-project/oxc/pull/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](/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.

## 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.
