DEV Community

楊東霖
楊東霖

Posted on • Originally published at devtoolkit.cc

Prettier vs ESLint: Formatting vs Linting Explained (Setup Guide)

Introduction

If you've ever worked on a JavaScript or TypeScript project with more than one developer, you've probably encountered the eternal debate: tabs vs spaces, semicolons vs no semicolons, single quotes vs double quotes. These arguments can derail entire code reviews. That's where Prettier and ESLint come in — two tools that solve related but fundamentally different problems.

Many developers confuse Prettier and ESLint or assume they do the same thing. In reality, they complement each other beautifully when configured correctly — but can cause frustrating conflicts when set up poorly. This guide will walk you through exactly what each tool does, how they differ, how to configure them individually and together, and how to avoid the most common pitfalls.

Whether you're setting up a brand-new project or untangling a messy existing configuration, this article has everything you need. If you'd like to experiment with code formatting in your browser first, try our JavaScript Formatter tool.

What is Prettier?

Prettier is an opinionated code formatter. Its sole job is to take your code and reprint it in a consistent style. It doesn't care whether your code is correct, efficient, or follows best practices — it only cares about how it looks.

Prettier supports a wide range of languages including JavaScript, TypeScript, HTML, CSS, JSON, GraphQL, Markdown, and YAML. When you run Prettier, it parses your code into an abstract syntax tree (AST) and then reprints it from scratch according to its formatting rules.

Key Characteristics of Prettier

  • Opinionated by design — Prettier intentionally limits configuration options. This forces teams to stop arguing about style and accept a consistent default.
  • Deterministic output — Given the same input and configuration, Prettier always produces the same output regardless of the original formatting.
  • AST-based — Prettier parses your code into an AST and reprints it, meaning it understands the structure of your code rather than applying regex-based find-and-replace.
  • Multi-language — One tool handles JavaScript, TypeScript, CSS, HTML, JSON, and more.
  • Zero-config by default — Prettier works out of the box with sensible defaults. You can override a small set of options if needed.

What Prettier Handles

  • Indentation (tabs or spaces, and how many)
  • Line length and wrapping
  • Semicolons (add or remove)
  • Quote style (single or double)
  • Trailing commas
  • Bracket spacing
  • JSX quote style
  • End-of-line characters

What is ESLint?

ESLint is a static analysis tool (linter) for JavaScript and TypeScript. Its primary job is to find and report patterns in your code that are likely bugs, violate best practices, or don't conform to your team's coding standards. While ESLint also has some formatting rules, its core strength is code quality analysis.

ESLint works by parsing your code and running a set of configurable rules against the resulting AST. Each rule can be turned off, set to warn, or set to error. Many rules also come with auto-fix capabilities.

Key Characteristics of ESLint

  • Highly configurable — Hundreds of built-in rules, plus thousands of community plugins.
  • Catches real bugs — Rules like no-unused-vars, no-undef, and eqeqeq catch actual programming errors.
  • Enforces best practices — Rules like no-eval, no-implicit-globals, and prefer-const encourage better code.
  • Extensible via plugins — Plugins for React, Vue, TypeScript, accessibility, testing libraries, and more.
  • Auto-fixable — Many rules can automatically fix issues with --fix.

What ESLint Handles

  • Unused variables and imports
  • Undefined variables
  • Unreachable code
  • Type coercion issues (== vs ===)
  • Missing return statements
  • React hooks rules (with plugin)
  • Accessibility issues (with plugin)
  • Import ordering and resolution
  • Naming conventions

Key Differences: Formatting vs Linting

The fundamental difference comes down to this: Prettier handles how your code looks; ESLint handles how your code works.

Aspect Prettier ESLint
**Primary purpose** Code formatting Code quality & bug detection
**Configuration** Minimal (intentionally) Extensive (hundreds of rules)
**Auto-fix** Always rewrites entire file Fixes only specific rule violations
**Languages** JS, TS, HTML, CSS, JSON, etc. JS, TS (with parser)
**Catches bugs** No Yes
**Enforces style** Yes (formatting only) Yes (code patterns & some formatting)
**Opinioned** Very (by design) Configurable
**Plugin ecosystem** Small (language parsers) Huge (React, Vue, a11y, etc.)

An Analogy

Think of it like writing an essay. Prettier is like a typesetter — it ensures consistent margins, font sizes, and paragraph spacing. ESLint is like a grammar checker and editor — it catches spelling errors, run-on sentences, and logical inconsistencies. You need both for a polished final product.

Configuration Examples

Prettier Configuration (.prettierrc)

Prettier's configuration is intentionally minimal. Create a .prettierrc file in your project root. You can format JSON config files easily with our JSON Formatter.


Enter fullscreen mode Exit fullscreen mode

You can also use a .prettierrc.js file for JavaScript-based configuration:


Enter fullscreen mode Exit fullscreen mode

Prettier Ignore File (.prettierignore)

Create a .prettierignore to exclude files from formatting:

node_modules
dist
build
coverage
*.min.js
package-lock.json
Enter fullscreen mode Exit fullscreen mode

ESLint Configuration (.eslintrc.json)

ESLint's configuration is far more extensive. Here's a solid starting point for a modern JavaScript/TypeScript project:


Enter fullscreen mode Exit fullscreen mode

ESLint for TypeScript

For TypeScript projects, you'll need the TypeScript parser and plugin:


Enter fullscreen mode Exit fullscreen mode

ESLint for React

React projects benefit from additional plugins:


Enter fullscreen mode Exit fullscreen mode

Using Prettier and ESLint Together

This is where most developers run into trouble. Both Prettier and ESLint have opinions about formatting, and when their opinions clash, you get an endless loop of conflicting fixes. The solution is eslint-config-prettier.

The Problem

ESLint has formatting rules like indent, quotes, and semi. Prettier also controls indentation, quotes, and semicolons. If ESLint says "use double quotes" but Prettier says "use single quotes," every save triggers a conflict. ESLint auto-fix changes them to double quotes, then Prettier changes them back to single quotes.

The Solution: eslint-config-prettier

The eslint-config-prettier package disables all ESLint rules that conflict with Prettier. This way, ESLint handles code quality while Prettier handles formatting with zero overlap.

Step-by-Step Setup

Step 1: Install dependencies

npm install --save-dev prettier eslint eslint-config-prettier
Enter fullscreen mode Exit fullscreen mode

Step 2: Configure ESLint to use eslint-config-prettier

Add "prettier" as the last item in your extends array. This is critical — it must be last so it overrides any conflicting rules from other configs:


Enter fullscreen mode Exit fullscreen mode

Step 3: Configure Prettier

Create your .prettierrc:


Enter fullscreen mode Exit fullscreen mode

Step 4: Add scripts to package.json


Enter fullscreen mode Exit fullscreen mode

ESLint Flat Config (eslint.config.js)

If you're using the newer ESLint flat config format (ESLint v9+), here's the equivalent setup:


Enter fullscreen mode Exit fullscreen mode

Common Conflicts and Fixes

Even with eslint-config-prettier, teams still run into issues. Here are the most common problems and their solutions.

Conflict 1: "prettier" Not Last in Extends

Symptom: ESLint and Prettier fight over formatting on every save.

Fix: Ensure "prettier" is the absolute last entry in your extends array. If you add a plugin after it, that plugin's formatting rules will override the disable.


Enter fullscreen mode Exit fullscreen mode

Conflict 2: ESLint Formatting Rules Still Active

Symptom: ESLint reports errors on formatting issues that Prettier should handle.

Fix: Run the eslint-config-prettier CLI helper to check for conflicts:

npx eslint-config-prettier .eslintrc.json
Enter fullscreen mode Exit fullscreen mode

This command lists any ESLint rules that conflict with Prettier so you can disable them manually.

Conflict 3: Different Line Endings (CRLF vs LF)

Symptom: Prettier reformats every line in a file, or Git shows changes on lines that look identical.

Fix: Set "endOfLine": "lf" in your .prettierrc and configure Git:

git config --global core.autocrlf input
Enter fullscreen mode Exit fullscreen mode

Also add an .editorconfig file:

[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = space
indent_size = 2
Enter fullscreen mode Exit fullscreen mode

Conflict 4: HTML/JSX Attribute Formatting

Symptom: Prettier wraps JSX attributes differently than expected, and ESLint complains about the result.

Fix: This is usually caused by having react/jsx-max-props-per-line or similar ESLint rules still enabled. With eslint-config-prettier, these should be disabled automatically. If not, disable them manually:


Enter fullscreen mode Exit fullscreen mode

Conflict 5: Import Order

Symptom: Prettier and an ESLint import sorting plugin fight over import order.

Fix: Prettier does not sort imports by default. If you want sorted imports, use eslint-plugin-import with the import/order rule, or use the @trivago/prettier-plugin-sort-imports Prettier plugin — but do not use both simultaneously.

Editor Integration

Proper editor integration is what makes these tools truly powerful. Instead of running commands manually, your editor formats and lints as you work.

VS Code Setup

Install the following extensions:

  • Prettier - Code formatter (esbenp.prettier-vscode)
  • ESLint (dbaeumer.vscode-eslint)

Then configure your .vscode/settings.json:


Enter fullscreen mode Exit fullscreen mode

This configuration means: on save, ESLint auto-fixes code quality issues first, then Prettier formats the file. The order matters — ESLint fixes should happen before Prettier formatting to avoid conflicts.

WebStorm / JetBrains IDEs

  • Go to Settings > Languages & Frameworks > JavaScript > Prettier
  • Check "On save" and "On Reformat Code action"
  • ESLint is automatically detected from your project's config

Neovim Setup

If you use Neovim with LSP, configure null-ls or conform.nvim for Prettier and use nvim-lspconfig for ESLint:


Enter fullscreen mode Exit fullscreen mode

CI/CD Setup

Running Prettier and ESLint in your CI/CD pipeline ensures that no unformatted or problematic code reaches your main branch.

GitHub Actions Example

name: Lint and Format Check
on:
  pull_request:
    branches: [main]

jobs:
  quality:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'

      - run: npm ci

      - name: Check formatting
        run: npx prettier --check .

      - name: Run linter
        run: npx eslint . --ext .js,.jsx,.ts,.tsx
Enter fullscreen mode Exit fullscreen mode

Note the use of prettier --check instead of prettier --write in CI. The --check flag exits with a non-zero code if any file isn't formatted, without actually modifying files.

Pre-commit Hooks with Husky and lint-staged

For catching issues before they even reach CI, set up pre-commit hooks:

npm install --save-dev husky lint-staged
npx husky init
Enter fullscreen mode Exit fullscreen mode

Add to your package.json:


Enter fullscreen mode Exit fullscreen mode

Update the Husky pre-commit hook at .husky/pre-commit:

npx lint-staged
Enter fullscreen mode Exit fullscreen mode

This runs ESLint and Prettier only on the files you've staged for commit, keeping your hook fast even in large repositories.

When to Use Each Tool

Use Prettier When...

  • You want consistent formatting across your entire codebase with zero debate
  • You're formatting non-JavaScript files like JSON, CSS, HTML, Markdown, or YAML
  • You want a zero-config or minimal-config solution
  • You're tired of formatting discussions in code reviews
  • You need deterministic output regardless of input formatting

Use ESLint When...

  • You want to catch bugs and enforce coding best practices
  • You need framework-specific rules (React hooks, Vue composition API, etc.)
  • You want to enforce naming conventions or import ordering
  • You need custom rules specific to your project or organization
  • You want to gradually improve code quality with warnings before enforcing errors

Use Both Together When...

  • You want the best of both worlds — which is most projects
  • You want Prettier to handle all formatting and ESLint to handle all code quality
  • You're working on a team and want to eliminate both style debates and common bugs
  • You're building a production application that needs to meet quality standards

Summary Decision Table

Scenario Recommendation
Solo hobby project Prettier alone is often enough
Small team, JS/TS project Both with eslint-config-prettier
Large enterprise codebase Both, plus custom ESLint plugins
Non-JS files only (CSS, JSON, MD) Prettier only
Legacy project with no formatting Add Prettier first, then ESLint gradually

Advanced Tips

Per-file Overrides

Both tools support per-file configuration overrides. In ESLint:


Enter fullscreen mode Exit fullscreen mode

In Prettier, use the overrides field in .prettierrc:


Enter fullscreen mode Exit fullscreen mode

Disabling Rules Inline

Sometimes you need to disable a rule for a specific line or block. ESLint supports inline comments:

// eslint-disable-next-line no-console
console.log('Debug info');

/* eslint-disable no-unused-vars */
const reservedForLater = true;
/* eslint-enable no-unused-vars */
Enter fullscreen mode Exit fullscreen mode

For Prettier, use prettier-ignore comments:

// prettier-ignore
const matrix = [
  [1, 0, 0],
  [0, 1, 0],
  [0, 0, 1],
];
Enter fullscreen mode Exit fullscreen mode

Migrating a Large Codebase

If you're adding Prettier to an existing project, format everything at once in a single commit. This creates a clear boundary in your Git history. Use git blame --ignore-rev to tell Git to skip that formatting commit when assigning blame:

# Format everything
npx prettier --write .

# Commit the formatting change
git add -A
git commit -m "chore: apply prettier formatting"

# Add the commit hash to .git-blame-ignore-revs
echo "abc123def456 # chore: apply prettier formatting" >> .git-blame-ignore-revs
git config blame.ignoreRevsFile .git-blame-ignore-revs
Enter fullscreen mode Exit fullscreen mode

For ESLint, a gradual approach works better. Start with "warn" severity for new rules, fix violations over time, then switch to "error" once the codebase is clean.

Conclusion

Prettier and ESLint are not competitors — they are complementary tools that solve different problems. Prettier eliminates all formatting debates by enforcing a consistent style automatically. ESLint catches bugs, enforces best practices, and helps you write more reliable code.

The ideal setup for most projects is:

  • Install both Prettier and ESLint
  • Use eslint-config-prettier to disable conflicting rules
  • Configure your editor to format on save (Prettier) and auto-fix on save (ESLint)
  • Set up pre-commit hooks with Husky and lint-staged
  • Run both checks in CI/CD to catch anything that slips through

This combination gives you a codebase that is both consistently formatted and free of common bugs and anti-patterns. Your code reviews can focus on architecture, logic, and design instead of arguing about semicolons.

Ready to start formatting your code right now? Try our JavaScript Formatter for quick browser-based formatting, or use our JSON Formatter to clean up your configuration files before committing them to your project.

Free Developer Tools

If you found this article helpful, check out DevToolkit — 40+ free browser-based developer tools with no signup required.

Popular tools: JSON Formatter · Regex Tester · JWT Decoder · Base64 Encoder

🛒 Get the DevToolkit Starter Kit on Gumroad — source code, deployment guide, and customization templates.

Top comments (0)