rustperformancefrontendnews

Rust JS Tooling 2025: Why Biome, Oxc, and Rolldown Change Everything

Explore how Rust-powered tools like Biome.js and Rolldown are delivering 10x performance gains and revolutionizing the JavaScript ecosystem in 2025.

DataFormatHub Team
Dec 31, 202511 min
Share:
Rust JS Tooling 2025: Why Biome, Oxc, and Rolldown Change Everything

The JavaScript tooling landscape is undergoing a significant transformation, driven by the practical advantages of Rust. As of late 2025, we're seeing these Rust-based tools mature, offering tangible performance gains and a more robust development experience. Having spent considerable time putting Biome.js, Oxc, and Rolldown through their paces on complex projects, I can tell you that the shift isn't just hype; it's a sturdy evolution of our core development infrastructure, much like how Modern CLI Deep Dive: Why Rust and GPU Terminals Change Everything in 2025 explores the terminal space.

Rust's appeal in this domain is straightforward: its focus on memory safety, zero-cost abstractions, and robust concurrency models directly translates to faster, more reliable tools. Where JavaScript-based tools often hit performance ceilings due to the overhead of the runtime and garbage collection, Rust-compiled binaries execute at near-native speeds. This is particularly critical for CPU-bound tasks like parsing, linting, formatting, and bundling, which are ubiquitous in modern frontend workflows.

Let me walk you through the recent developments and how these tools are practically reshaping our daily routines, from local development to CI/CD pipelines.

Biome.js 2.0: The Unified Toolchain Matures

Biome.js has always aimed to be the all-in-one frontend toolchain, consolidating formatting, linting, and import organization. With the beta release of version 2.0 in March 2025 and its subsequent stabilization around June 2025, it has solidified its position as a compelling alternative to fragmented JavaScript-based setups like ESLint and Prettier.

The core architectural advantage of Biome lies in its unified approach. Instead of multiple tools parsing your code independently, Biome parses code just once, constructs a single Abstract Syntax Tree (AST), and then reuses that AST for all subsequent operations—linting, formatting, and import sorting. This "one-parse, multiple-passes" strategy eliminates massive computational overhead, which is why it consistently delivers impressive speedups.

One of the most significant advancements in Biome 2.0 is the introduction of a plugin system, allowing developers to write custom lint rules using GritQL. This addresses a long-standing request from the community, extending Biome's capabilities beyond its built-in rule set. Furthermore, type-aware rules, such as noFloatingPromises, have been implemented, providing a deeper level of static analysis without requiring the full TypeScript compiler, although integration with TypeScript's API is on the roadmap for future enhancements.

You can use this JSON Formatter to verify your structure when editing your biome.json file. Let's look at a practical configuration, demonstrating how to enable these new features and tailor Biome to your project.

{
  "$schema": "https://biomejs.dev/schemas/2.0.5/schema.json",
  "organizeImports": {
    "enabled": true
  },
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true,
      "style": {
        "useSingleVarDeclarator": "error",
        "noVar": "error"
      },
      "complexity": {
        "noExtraBooleanCast": "warn"
      },
      "suspicious": {
        "noFloatingPromises": "error"
      }
    },
    "ignore": ["node_modules/", "dist/"]
  },
  "formatter": {
    "enabled": true,
    "indentStyle": "space",
    "indentWidth": 2,
    "lineWidth": 100,
    "quoteStyle": "single"
  },
  "javascript": {
    "formatter": {
      "quoteStyle": "single",
      "jsxQuoteStyle": "double"
    }
  },
  "vcs": {
    "enabled": true,
    "clientKind": "git",
    "root": "./"
  },
  "overrides": [
    {
      "include": ["**/*.test.ts", "**/*.spec.ts"],
      "linter": {
        "rules": {
          "security": {
            "noConsoleLog": "off"
          }
        }
      }
    }
  ]
}

This biome.json snippet illustrates several points. We enable import organization, the linter with recommended rules, and specific style rules like useSingleVarDeclarator and noVar. Critically, the noFloatingPromises rule is enabled under suspicious, leveraging the new type information capabilities to catch unhandled promise rejections. The formatter is configured for 2-space indentation and a 100-character line width, with JavaScript-specific overrides for quote styles. The vcs section enables Git-aware scanning, allowing Biome to process only changed files, a massive time-saver in large repositories. Finally, the overrides array demonstrates how to selectively disable rules for specific file patterns, such as allowing console.log statements within test files. This level of granular control, coupled with its performance, makes Biome a sturdy choice for maintaining code quality.

Oxc: The High-Performance Foundation

Oxc, or the Oxidation Compiler, is not a direct user-facing tool in the same way Biome or Rolldown are. Instead, it serves as a collection of high-performance, modular JavaScript and TypeScript tools written in Rust, forming a foundational layer for other projects. It's the engine under the hood for many next-generation tools, including Rolldown.

Oxc's architecture is built on principles of performance, correctness, developer experience, and modular composability. This means its components—such as oxc-parser, oxc-linter, oxc-transform, oxc-minify, and oxc-resolver—can be used independently or composed into complete toolchains. The parser, for instance, is notably fast, capable of linting over 4800 files in the VS Code repository in approximately 0.7 seconds. This speed is achieved through rigorous performance engineering, including zero-copy parsing and leveraging Rust's efficiency.

Let's consider oxlint, the standalone linter component of Oxc. It's designed to be a production-ready linter with sensible defaults, offering a fast and opinionated alternative to ESLint.

To quickly lint a project with oxlint:

npx oxlint@latest

This command will run oxlint with its default, opinionated rules. For more control, you can generate a configuration file:

npx oxlint@latest --init

This might create a .oxlintrc.json (or similar, depending on the latest stable version) where you can enable or disable specific rules. The real power of Oxc, however, often lies in its internal APIs. Imagine you're building a custom code transformation tool. You could leverage oxc-parser to get a lightning-fast AST:

import { parseSync } from 'oxc-parser';

const code = `
  function greet(name: string) {
    console.log(\`Hello, \${name}!\`);
  }
  greet("World");
`;

const ast = parseSync(code, { sourceType: 'module', typescript: true });
console.log(JSON.stringify(ast, null, 2));

This conceptual example highlights how oxc-parser provides a direct, high-performance route to a JavaScript/TypeScript AST. Developers can then build custom tooling on top of this robust foundation, enabling advanced static analysis, code modifications, or even custom linters that operate at speeds previously unattainable with JavaScript-native parsers.

Rolldown & Vite: The Next Generation Bundler

The web development community has been keenly watching the integration of Rolldown, a Rust-powered JavaScript bundler, into Vite. Announced as a key component for Vite 6, rolldown-vite entered technical preview around May 2025, with the ambitious goal of replacing both esbuild (for dependency pre-bundling) and Rollup (for production builds) with a single, unified Rust-native solution.

Rolldown's architecture is designed from the ground up in Rust to deliver performance on par with esbuild and significantly faster than Rollup – often 10 to 30 times quicker. This speed isn't just about faster production builds; it's about fundamentally improving the development experience. The roadmap for Rolldown in Vite involves three phases: a standalone rolldown-vite package for early feedback, merging into the main Vite codebase with an opt-in "Full Bundle Mode" for development, and eventually becoming the default bundler.

The "Full Bundle Mode" is particularly interesting. It aims to unify the development and production experiences, serving bundled files during development while maintaining Vite's signature fast startup times and efficient Hot Module Replacement (HMR) on top of ESM output. This promises consistent behavior between development and production, reducing network overhead on page refreshes, especially for larger applications.

To get a feel for rolldown-vite, you would typically alias it in your package.json:

{
  "name": "my-vite-app",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@vitejs/plugin-react": "^4.2.1",
    "vite": "^5.0.0",
    "rolldown-vite": "^0.3.0"
  },
  "pnpm": {
    "overrides": {
      "vite": "npm:rolldown-vite@latest"
    }
  }
}

In this package.json, we're using pnpm overrides to tell the package manager to use rolldown-vite whenever vite is requested. This allows you to test the Rust-powered bundler as a drop-in replacement.

While Rolldown is designed to be largely compatible with the existing Rollup plugin API, some plugins relying on esbuild for internal transformations might require updates, as rolldown-vite now leverages Oxc for all internal transformations and minification, making esbuild an optional dependency. This consolidates the foundational layer, leading to further performance gains.

For vite.config.js, Rolldown largely respects existing Vite configurations, but you might see new options emerge specifically for fine-tuning its bundling behavior, especially around chunk splitting and advanced optimizations.

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  build: {
    minify: 'oxc',
    rollupOptions: {
      output: {
        manualChunks(id) {
          if (id.includes('node_modules')) {
            return id.toString().split('node_modules/')[1].split('/')[0].toString();
          }
        }
      }
    }
  }
});

Bridging the Divide: NAPI-RS and WebAssembly

The seamless integration of Rust-based tools into the JavaScript ecosystem is largely facilitated by projects like NAPI-RS. NAPI-RS is a framework that allows you to build Node.js addons in Rust, providing a robust and efficient bridge between the two languages. It abstracts away the complexities of Node-API (N-API), enabling Rust developers to expose high-performance functionalities to JavaScript with minimal overhead.

The significance of NAPI-RS cannot be overstated. It allows performance-critical parts of web tooling – such as parsers, transformers, and bundlers – to be written in Rust, compiled to native code, and then consumed directly within Node.js environments. This gives us the best of both worlds: Rust's speed and memory safety for heavy lifting, and JavaScript's flexibility and vast ecosystem for the orchestration layer.

A key advantage of NAPI-RS is its "zero-config build" capability, simplifying the compilation and linking process across different platforms. It supports a wide array of Node.js runtime platforms, ensuring broad compatibility. Moreover, NAPI-RS has expanded its capabilities to support compilation to WebAssembly, meaning that these Rust-powered native addons can run not only in Node.js but potentially directly in the browser, opening up new avenues for client-side performance.

Let’s look at a conceptual NAPI-RS binding to understand how a Rust function can be exposed to JavaScript:

use napi_derive::napi;

#[napi]
pub fn calculate_heavy_computation(input: u32) -> u32 {
  let mut result = 0;
  for i in 0..input {
    result += i;
  }
  result
}

And in your JavaScript/TypeScript code:

const { calculateHeavyComputation } = require('./my-rust-addon.node');

console.time('Rust computation');
const rustResult = calculateHeavyComputation(1_000_000_000);
console.timeEnd('Rust computation');

Performance Deep Dive: Benchmarks and Real-World Gains

The consistent theme across Biome.js, Oxc, and Rolldown is a dramatic leap in performance compared to their JavaScript-native predecessors. These aren't incremental gains; we're talking about orders of magnitude faster execution for many critical tasks.

For Biome, community benchmarks and internal testing consistently show it performing 10x faster than ESLint and Prettier combined, with some reports indicating up to 25x faster formatting and 15x faster linting. This speed stems directly from Rust's core advantages:

  1. Memory Safety without GC Overhead: Rust's ownership and borrowing system guarantees memory safety at compile time, eliminating the need for a runtime garbage collector.
  2. Zero-Cost Abstractions: Rust's abstractions compile down to highly optimized machine code with no runtime cost.
  3. Concurrency and Parallelism: Rust's strong type system enables safe and efficient concurrency, allowing tools to leverage multiple CPU cores.

Rolldown's early benchmarks are equally impressive. Companies like GitLab reported build times reduced from 2.5 minutes to 40 seconds, alongside a staggering 100x reduction in memory usage. Excalidraw saw its build time drop from 22.9 seconds to 1.4 seconds.

Let's illustrate the parallelized architecture that makes this possible:

This parallelized architecture is the fundamental reason for the dramatic performance improvements. For tasks that are inherently CPU-bound and can be broken down into independent units, Rust's concurrency model provides a clear advantage.

Configuration Mastery: Unlocking Full Potential

While these Rust-based tools boast "minimal config" principles, understanding their configuration options is crucial for tailoring them to specific project needs. The biome.json file is the central hub for Biome, offering a unified interface for formatting, linting, and import organization.

Beyond the basic enablement of tools and rules, Biome provides advanced features like vcs integration and granular overrides. The vcs configuration, when enabled, allows Biome to automatically detect your Git client and root, enabling commands to operate only on changed files.

{
  "$schema": "https://biomejs.dev/schemas/2.0.5/schema.json",
  "vcs": {
    "enabled": true,
    "clientKind": "git",
    "root": "./"
  },
  "files": {
    "ignore": [
      "**/legacy-code/**/*",
      "*.d.ts"
    ],
    "include": ["src/**/*.ts", "src/**/*.tsx"]
  },
  "overrides": [
    {
      "include": ["components/**/*.tsx"],
      "linter": {
        "rules": {
          "a11y": {
            "noSvgWithoutTitle": "off"
          }
        }
      },
      "formatter": {
        "lineWidth": 120
      }
    }
  ]
}

For command-line execution, Biome offers several powerful flags:

  • biome check . --write: Runs formatting, linting, and import sorting, and applies fixes.
  • biome ci .: A read-only check command, ideal for CI pipelines.
  • biome format --write --staged: Formats only staged Git changes.
  • biome lint --since=origin/main: Lints only files changed since the origin/main branch.

Current Realities and Future Trajectories

While the Rustification of frontend tooling brings undeniable advantages, it's important to maintain a reality check. These tools, while rapidly maturing, are still evolving.

What works well:

  • Performance: The speed gains are real and immediately noticeable.
  • Unified Experience: Biome's single configuration for multiple tasks simplifies setup.
  • Foundational Stability: Oxc provides a highly performant and stable parsing layer.
  • Vite Integration: Rolldown's integration with Vite is on a clear path to becoming a default.

What's still clunky or experimental:

  • Ecosystem Maturity: The plugin ecosystem for Rust-native tools is still nascent.
  • Full Language Support: Biome 2.0 has a roadmap for HTML and CSS, but it's not fully comprehensive yet.
  • Debugging: Debugging Rust code via NAPI-RS can have a steeper learning curve.
  • Rolldown's Full Feature Parity: Ensuring full parity with every esoteric Rollup plugin will be an ongoing effort.

Expert Insight: Trend Prediction

My prediction for late 2025 and into 2026 is a continued convergence and specialization. We'll see more frameworks and build tools adopt foundational Rust components like Oxc directly, not just for parsing, but for transformation and minification, further reducing reliance on esbuild or Babel. The concept of a "unified toolchain" will expand beyond linting/formatting to deeply integrate with bundling and even testing, creating highly optimized, end-to-end Rust-powered development loops. This will lead to a new generation of framework-specific CLI tools that leverage these Rust primitives to offer unparalleled performance and a seamless developer experience.

In conclusion, the Rust-based tooling wave is not just a passing trend; it's a fundamental shift towards more efficient, reliable, and performant frontend development. Biome.js, Oxc, and Rolldown are at the forefront of this movement, offering tangible improvements today and laying the groundwork for an even faster, more integrated future.


Sources


🛠️ Related Tools

Explore these DataFormatHub tools related to this topic:


📚 You Might Also Like