Code Formatters Reviewed: Prettier, Biome, dprint and Ruff

Updated 2026-03-27 · By SPUNK13 · Back to spunk.bet

Formatters stopped being controversial around the time Prettier won the JavaScript argument. What changed since is speed and scope: Rust-based tools now format large repositories in under a second, and language-specific formatters have absorbed linting. Here is how the main options behave in practice.

Prettier: the safe default, and slow

Prettier formats JS, TS, JSX, CSS, SCSS, HTML, JSON, YAML, Markdown and GraphQL, with plugins for more. Its value is that the output is universally recognised and the config surface is deliberately tiny — printWidth, semi, singleQuote, trailingComma, tabWidth and a handful more. Its weakness is throughput: it is Node-based, and on a repository with a few thousand files a full prettier --write . takes tens of seconds. In watch mode on save that does not matter. In CI on a monorepo it does.

Biome: fast, Prettier-compatible, narrower

Biome is a Rust toolchain that formats and lints in one binary. It targets Prettier-identical output for JS/TS and reaches very high compatibility, so migration is mostly mechanical. Two commands cover everything: biome check --write . for lint and format, biome ci . for the read-only CI run. The catch is coverage — support for HTML and some CSS-adjacent formats has lagged behind Prettier, so mixed repositories often end up running both, which defeats part of the point.

dprint: plugin-based, good for polyglot repos

dprint is also Rust, but built around WASM plugins declared in dprint.json. You pin plugin versions explicitly, which makes formatting output reproducible across machines and CI in a way that floating npm ranges do not. It is the least popular of the three and the documentation assumes you already know what you want, but for a repo mixing TypeScript, Markdown, TOML and Dockerfiles it is the tidiest single configuration.

Python: Ruff has effectively ended the argument

Black defined the style; Ruff implemented it in Rust and added the linter. ruff format . is Black-compatible output at a fraction of the runtime, and ruff check --fix . replaces flake8, isort and a long list of plugins. Configure both in pyproject.toml under [tool.ruff]. If you are on Black and isort today, migrating is usually a twenty-minute job and the CI step drops from tens of seconds to under a second.

Languages where the decision is already made

Go has gofmt and there is no debate; use gofmt -l . in CI and note it exits 0 even when files are unformatted, so wrap it in test -z "$(gofmt -l .)". Rust has cargo fmt --check. Zig, Elm and Deno all ship formatters. In these ecosystems the formatter is part of the toolchain and arguing about style is a solved problem you inherited for free.

The migration cost nobody budgets

Reformatting an existing repository creates one enormous commit that ruins git blame. The fix is .git-blame-ignore-revs: put the reformat commit's SHA in that file, commit it, and run git config blame.ignoreRevsFile .git-blame-ignore-revs. Both the CLI and the major forges honour it. Do the reformat on a quiet day, merge every open branch first, and expect a round of conflicts on long-lived branches regardless.

What to pick

Want More?

Explore our complete collection of free tools and resources.

Visit spunk.bet
400+ Free Tools Free Casino Meme Generator Birth Charts Scam Database BPM Calculator