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.