I’ve been proclaiming loudly for several years now to “STOP USING ESLINT FOR FORMATTING”. My belief is that formatters such as Prettier and linters such as ESLint are fundamentally different tools built for different purposes. While you can use ESLint for formatting thanks to ESLint Stylistic, ESLint recommends using a separate dedicated formatter and typescript-eslint also recommends against using ESLint for formatting.
The following two tools have historically been used to help ESLint interact nicely with Prettier:
eslint-config-prettier: An ESLint shareable config that disables formatting-related rules
eslint-plugin-prettier: An ESLint plugin that runs Prettier as a rule inside ESLint
I believe neither tool is useful in most projects anymore. This blog post will explain the purpose of each of them, their differences, and why I generally don’t use either.
Recap: ESLint Customizations
ESLint works by letting individually configure “rules”, or checks on your codebase. ESLint will do the work of parsing your code into a format rules understand, passing the code to those rules, and letting you know about any reports emitted by those rules.
ESLint is highly extensible: meaning you can customize many aspects of how it runs. The most common ways to customize it are:
- Plugins: Provide a set of rules that are added to the list of rules available to be configured
- Shareable Configs: Provide configuration options for any number of rules - either as a standalone npm package or from part of a plugin
Note that plugins and shareable configs are two different things.
- Plugins make rules available without configuring those rules.
- Shareable configs configure rules that come with ESLint and/or were previously made available in plugins.
ESLint Customization Example: TypeScript
If you use ESLint to lint TypeScript code then you’re hopefully using all three customizations:
@typescript-eslint/parserto support parsing TypeScript code
@typescript-eslint/eslint-pluginto load in rules specific to TypeScript
- Shareable Config(s): Shared settings packaged with
@typescript-eslint/eslint-pluginthat configure many rules at once, such as
Note that the typescript-eslint shareable configs come from the
@typescript-eslint/eslint-plugin npm package.
plugin: prefix in front of them: that’s how ESLint knows where to find the configs.
eslint-config-prettier is a shareable config that disables formatting-related rules.
You can load it into your project by listing it under
"extends" array in your ESLint config:
// (shorthand for "eslint-config-prettier")
The sole purpose of
eslint-config-prettier is to turn rules off.
On the inside, it looks like an object with a bunch of properties whose values are
eslint-config-prettier Came To Be
Back in the day, popular shareable configs such as
eslint-config-airbnb were often used to enable many rules at once.
These configs were popular because they established a well-known, opinionated style guide and set of logical checks on code.
Their downside was that they were oftentimes too opinionated - even enabling formatting rules.
Developers got around those formatting rules by knowing that ESLint evaluates configs in the order they’re listed under
eslint-config-prettier could be placed last in a project’s ESLint config to turn off any formatting rules enabled by previous plugins.
// 1. Configures many ESLint rules, including enabling some formatting ones
// 2. Disables only the formatting rules from previous configs
By extending from
eslint-config-prettier last, projects could gain the benefits of those popular shareable configs without having to run formatting rules within ESLint.
eslint-config-prettier Is Often Unnecessary
Over the last few years, ESLint best practices have advanced in two ways (among others):
- ESLint core and most community plugins have determined that enabling overly opinionated rules -especially stylistic ones- in shareable configs makes developers dislike ESLint without much real benefit
- The recommended rulesets in ESLint and typescript-eslint have grown to include most of the beneficial logical rules that shareable configs such as
eslint-config-airbnbwere largely used for
As a result, many new projects haven’t felt a need to load in opinionated configs such as
Many projects start out with a much more straightforward set of configs:
- To start:
"eslint:recommended", ESLint’s built-in recommended configuration
- If using TypeScript:
"plugin:@typescript-eslint/recommended-type-checked"for the recommended TypeScript rules
- Any framework- or library-specific plugins, such as
If you don’t use a legacy ESLint shareable config that enables formatting rules, you probably don’t need
eslint-config-prettier at the end of the
"extends" list doesn’t do anything if nothing enabled formatting rules to begin with.
Therefore, most projects don’t gain any benefit from
Furthermore, two insidious points of confusion can arise from using
- Seeing a reference to “prettier” in an ESLint configuration can confuse developers new to the area.
- Nothing stops projects from manually re-enabling formatting rules under the ESLint configuration’s
I now recommend against including
eslint-config-prettier in most new projects.
💡 Not sure whether you can safely remove
"extends"? Try removing it, then running
npx eslint-config-prettier some/file.jsto see if it points out any conflicting rules. Running ESLint with
--print-configcan alternately print out the full list of lint rule configurations for a file.
eslint-plugin-prettier is an ESLint plugin that provides two things:
- A custom rule,
prettier/prettier, that runs all of Prettier inside a single ESLint rule
- A shareable config,
plugin:prettier/recommended, that enables the
For example, in ESLint’s legacy config format, you might enable it by extending its recommended config:
Extending that config:
"plugins"list of extended plugins, thereby loading in the
- Enables the
"extends"list of extended configs
The advantage of this approach is that you don’t need to separately configure Prettier alongside ESLint. You can have one file -your ESLint config- that enables both.
eslint-plugin-prettier Is Often Harmful
There are two big problems with running Prettier inside an ESLint rule the way
- Behavioral: it joins Prettier’s reports with ESLint’s, which in my experience confuses developers who aren’t familiar with the tools
- Performance: formatting is now blocked on all linting, which is often much slower than formatting
The performance point can become quite bad in projects that utilize type-checked rules.
prettier/prettieris the only lint rule that produces reports containing an auto-fixer, linting has to run twice
- If any other rules introduce auto-fixes, one or more additional cycles may be introduced from
prettier/prettierfixing formatting issues with those auto-fixes
😬 Keep in mind that lint rules don’t have visibility into formatting settings. Their auto-fixers aren’t likely to produce code that aligns to your formatter.
I strongly recommend you do not use
We even explicitly recommend against
eslint-plugin-prettier in the typescript-eslint formatting FAQs and typescript-eslint performance troubleshooting docs.
prettier/prettier is enabled in your ESLint configuration, the best step you can take is to remove it and uninstall the
eslint-plugin-prettier package altogether.
Failing that, you can disable the rule manually (
"prettier/prettier": "off" under
At that point you’ll still have the
eslint-config-prettier shareable config enabled.
Formatting and linting are two separate concerns.
Mixing the two can have negative impacts on the performance and understandability of your developer tooling.
My standard repository template,
create-typescript-app, keeps the two explicitly separate.
If your ESLint configuration references
eslint-config-prettier, I suggest you try to remove it from your config.
You probably don’t need it anymore.
If your ESLint configuration references
eslint-plugin-prettier, I strongly recommend you instead enable Prettier separately from ESLint.
prettier/prettier rule can introduce significant performance pain to your project.
No matter what tooling your ESLint configuration enables, if you haven’t overhauled it in a few years, I strongly recommend:
- Making sure
"eslint:recommended"is in your rule extensions
- If you’re using TypeScript:
- Making sure at least
plugin:@typescript-eslint/recommendedis enabled - or even better,
- Checking the
create-typescript-app, for any rules or plugins generally applicable to your project
- Making sure at least
- Checking github.com/dustinspecker/awesome-eslint for any additional plugins relevant to your project
💡 Configuring ESLint, Prettier, and TypeScript Together is a blog post of mine that goes more into how to configure these tools.
Happy linting, everyone! 🎉
Much appreciation to Anisha Malde for suggesting I write an explainer in this area and helping ideate contents. Thanks! 🙌
Thanks to Ben Scott, a maintainer of
eslint-config-prettier, for reviewing the post and suggesting clarifications and corrections on how
eslint-plugin-prettier is described.
Thanks to Simon Lydell, the original creator and a long-time maintainer of
eslint-config-prettier, for reviewing the post and suggesting the
npx eslint-config-prettier approach.
We should also note that although I personally disagree with using
eslint-plugin-prettier now, they have been legitimately useful tools for many years.
I like to think that they’ve helped many folks onboard to formatting and/or linting their code.
Heck, I’d still rather work in a project that uses them than a project that doesn’t auto-format at all!
Many thanks to all their contributors and maintainers over the years!
Liked this post? Thanks! Let the world know: