Prettier is Fast

July 11, 2025

Today I learned Prettier is now as fast as the new breed of formatters written in Rust. The key is to combine their new OXC plugin with an experimental, high-performance CLI.

On my project of ~375 TypeScript/TSX files (23k lines of code), the speed-up was dramatic:

  • Before: ~11 seconds
  • With just the OXC plugin: ~6 seconds
  • With OXC plugin + --experimental-cli: ~1 second

The change is night and day. It makes Prettier feel instant again.

Here’s how to enable it:

First, install the new @prettier/plugin-oxc. It's an official plugin but isn't bundled with the core package.

npm install --save-dev prettier @prettier/plugin-oxc
# or pnpm add -D -w prettier @prettier/plugin-oxc

Next, add it to your .prettierrc file.

{
  "plugins": ["@prettier/plugin-oxc"]
}

Finally, run Prettier with the --experimental-cli flag.

prettier . --check --experimental-cli

That's it. It just works.

This was all part of the Prettier 3.6 release. The CLI improvements and the Rust-based parser from OXC are separate features, but they compose brilliantly. Definitely worth the two minutes it takes to set up.


Addendum: Simplifying my Turborepo Config

This speed-up let me immediately simplify my Turborepo configuration. I was previously caching formatting tasks per-workspace to avoid re-running them unnecessarily, but the setup added complexity to my turbo.json. With Prettier now running in about a second for my entire monorepo, that complexity is no longer justified.

This follows Turborepo's own advice for exceptionally fast tools like Biome, which now applies to Prettier as well. Their documentation recommends keeping things simple with a root task if a tool is fast enough not to be a bottleneck.

The main idea is to trade a small amount of cache efficiency for a much simpler configuration. Instead of caching format for each package, I now run a single, uncached format command from the root.

Here’s what I did.

First, I added scripts to my root package.json to run Prettier across the entire project.

// ./package.json
{
  "scripts": {
    // ... other scripts
    "format": "prettier --ignore-path ./.prettierignore . --ignore-unknown --write",
    "format:check": "prettier --ignore-path ./.prettierignore . --ignore-unknown --check"
  }
}

Then, I updated my turbo.json to treat these as uncached root tasks. The //# syntax tells Turbo to run this script from the monorepo root, not within each workspace.

// ./turbo.json
{
  "tasks": {
    // ... other tasks like "build"

    "//#format": {
      "cache": false
    },
    "//#format:check": {
      "cache": false
    }

    // I no longer need per-package "format" tasks defined here
  }
}

The result is a simpler turbo.json file that's easier to manage. I no longer have to define inputs and outputs for formatting, and the monorepo-wide command is more straightforward. It's a great example of how a significant performance improvement in a single tool can have positive, simplifying ripple effects across your entire development workflow.