Which code formatter should you use: Prettier, Ruff, Black, or dprint?
· 5 min read
Prettier vs Ruff vs Black vs dprint: which code formatter to pick for JavaScript, TypeScript, Python, or Lua, plus migration from abandoned tools.

Pick Prettier for JavaScript, TypeScript, CSS, HTML, and the rest of the frontend ecosystem. Pick Ruff for Python unless you want Black's frozen style and do not care about speed. Pick dprint if you want one configurable tool across several languages, and StyLua if you write Lua or Luau.
This is a comparison, not a feature list. Below: what each formatter does, when to choose it, when not to use one at all, and how to move off abandoned tooling without rewriting your config by hand.
When not to use a formatter at all
A formatter is not free. It adds a config file, a CI step, and a pull-request debate about whether to run it on save. If your repo is under 500 lines and one person maintains it, a formatter is overhead, not a benefit. Single-file scripts and throwaway prototypes do not need one either. The consensus says every repo needs a formatter; that is not true.
The honest question is whether formatting is your actual bottleneck. Our CodeBeautify alternative page ranks at position 7.6 for its own name with 2,325 impressions and zero clicks - searchers want a direct recommendation, not a list. If you are not getting style debates in pull requests, you do not have a formatting problem.
Migrating off abandoned tooling
The best reason to switch is that your current tool may no longer be maintained. Sublime-HTMLPrettify, which formatted HTML, CSS, JavaScript, JSON, React, and Vue inside Sublime Text, last committed to master on February 13, 2019. That is more than six years without a maintainer, and readers still on it are running unsupported tooling. The repository history shows the Feb 13, 2019 date on master; an older context note claimed October 12, 2023, which we could not verify, so this post uses the verified date.
Switching is low-risk. Ruff is an explicit drop-in replacement for Black, and dprint offers wrapper plugins including Prettier, Biome, oxc, Ruff, and StyLua. You do not rewrite your formatting rules by hand: point the new tool at the code, run it once, and commit the result. The diff is one commit, and formatter output is deterministic, so review is straightforward.
Prettier: the JavaScript ecosystem default
Prettier is an opinionated code formatter for JavaScript, JSX, Angular, Vue, Flow, TypeScript, CSS, Less, SCSS, HTML, JSON, GraphQL, Markdown, MDX, YAML, and more. It parses your code and re-prints the abstract syntax tree from scratch, so the original styling is discarded and replaced by one consistent style; line length drives wrapping. The point is to end style debates: run Prettier and go with that style. Prettier's documentation describes it as a fully automatic style guide, and the why-prettier page frames adoption as low-overhead across repos.
What the output looks like (illustrative example, not a personal timing):
Before:
function add(a,b){return a+b;}
After Prettier:
function add(a, b) {
return a + b;
}
Use Prettier when:
- Your stack is JavaScript, TypeScript, React, Vue, or Angular.
- You want zero configuration: install it, enable format-on-save in your editor, and add it to pre-commit and CI.
- You work on a team and want formatting to stop being a pull-request topic.
The trade-off is control. Prettier offers few options, so if your team bikesheds over print width or bracket spacing, Prettier removes the choice by design. That is the feature, not the bug.
Black: Python's uncompromising formatter
Black is "the uncompromising code formatter": opinionated, near-zero config, deterministic, and built so that "Blackened code looks the same regardless of the project." It trades control over formatting minutiae for speed, determinism, and freedom from pycodestyle nagging, and it produces the smallest diffs possible to keep code review fast. Black's documentation positions it as stable and PSF-backed.
Use Black when:
- You write Python and want a style that never changes between versions.
- You value the smallest possible diffs in review over configurability.
- You do not want to maintain a formatter config at all.
Black is Python only. If your repo mixes Python with JavaScript or CSS, you still need a second formatter for those files, which is exactly the split Prettier-plus-Black teams live with.
Ruff: the fast Python linter and formatter
Ruff is an extremely fast Python linter and code formatter written in Rust, and the Astral project claims it runs 10-100 times faster than Flake8 and formatters like Black. It is configured through pyproject.toml and can replace Flake8, Black, isort, pydocstyle, pyupgrade, and autoflake while running tens to hundreds of times faster. Ruff's documentation describes it as drop-in parity with Flake8, isort, and Black.
What the output looks like (illustrative example, not a personal timing):
Before:
def add(a,b): return a+b
After Ruff:
def add(a, b):
return a + b
Use Ruff when:
- You write Python and want one binary that lints and formats.
- You are migrating from Black and want the same style with much faster runs.
- Your CI spends minutes on linting and formatting; Ruff cuts that to seconds.
The catch: Ruff is opinionated like Black, so it is not "Black with options." It is Black-style output produced by a faster tool. If you need Black's exact, frozen style, Black itself is still the safer stay-put choice.
dprint and StyLua: the niche choices
dprint is a pluggable, configurable code formatting platform that unifies several formatters through per-language plugins - TypeScript/JavaScript, JSON/JSONC, Markdown, TOML, Dockerfile, SQL, plus wrapper plugins for Prettier, Biome, oxc, Ruff, and StyLua. It is a single binary you configure for the languages you actually use. The dprint project describes it exactly that way.
Use dprint when one repo holds several languages and you do not want a formatter per language. The downside is plugin maintenance: you are assembling a formatter from plugins rather than adopting a community standard.
StyLua is a deterministic formatter for Lua 5.1-5.4, LuaJIT, Luau, and CfxLua. Inspired by Prettier, it parses and re-prints from scratch and is configured through .stylua.toml. The StyLua project is actively maintained. Use it if you write Lua or Luau; skip it if you do not.
Quick decision table
| Your stack | Pick this | Why |
|---|---|---|
| JavaScript / TypeScript / frontend | Prettier | Ecosystem standard, zero config, editor and CI ready |
| Python, speed matters | Ruff | Linter and formatter in one Rust binary, fast |
| Python, frozen style preferred | Black | Deterministic, smallest diffs, PSF-backed |
| Several languages in one repo | dprint | One configurable tool, language plugins |
| Lua / Luau | StyLua | Deterministic, opinionated, actively maintained |
| Still on Sublime-HTMLPrettify | Ruff or dprint | Migrate off tooling last touched in 2019 |
Related tools
Formatters shape how code looks; minifiers shrink how much of it ships. If your pain is file size rather than style, try:
- CSS Minifier - minifies CSS for production.
- HTML CSS JS Minifier - minifies HTML, CSS, and JavaScript together.
- JSON Formatter Validator - formats and validates JSON, a neighbour if your main pain is JSON rather than source code.
For more tool comparisons, see the Tool Alternatives Hub. If you want to paste code into a browser instead of adopting a formatter, the CodeBeautify alternative page covers online beautifiers - a different product category from the developer formatters above.

Written by
Beatrice Mwangi
A formatter settles arguments that should never have been opened, which leaves one decision worth having: which tool the project commits to. Everything after that is configuration. The current field has converged on two implementations with the same goal. Prettier has the larger plugin ecosystem and a stable output model; Biome is written in Rust, is substantially faster on large files, and covers formatting and linting in one pass with its own configuration.
Both produce readable output and both will change a file the moment somebody saves it. Adopting one is a project decision, not a preference. Configuration discovery is where people get stuck. Both tools read a configuration file, resolve it from the directory being formatted, and ignore paths listed in an ignore file.
Running a formatter from the wrong directory changes which configuration applies, so the output changes without anybody editing the rules. Format and lint are different jobs with an ordering. A linter reports problems; a formatter rewrites files. Running lint with a fix option and formatting at the same time produces two passes over the same file and a diff nobody can read.
I fix the order first, then configure. I have a view on print width and no interest in arguing it. A formatter that disagrees with hand-written code produces a first commit of pure reformatting, and that commit has to be separate from any functional change or the review is unreadable. The practical recommendation on every page is the same: adopt one tool, format once on a clean branch, and then let it run on save forever.