ESLint and Prettier: Code Quality Automation for JavaScript
In this tutorial, you'll learn ESLint and Prettier setup including rules configuration, plugin integration, format-on-save, and integrating linters into CI/CD pipelines for consistent code quality.
Why Linting and Formatting Matter
Code reviews should focus on logic, not formatting. Inconsistent indentation, missing semicolons, and unused variables waste reviewer time and create friction in pull requests. ESLint catches bugs and enforces code quality rules. Prettier enforces consistent formatting automatically. Together, they eliminate an entire class of code review comments.
By the end of this guide, you will configure ESLint and Prettier for any JavaScript project, set up format-on-save, and integrate linting into CI/CD.
What are ESLint and Prettier?
ESLint is a pluggable linter for JavaScript and TypeScript. It analyzes code for potential errors, enforces coding standards, and can auto-fix certain issues. Prettier is an opinionated code formatter that parses code and reprints it with consistent style.
flowchart LR A[Source Code] --> B[ESLint] A --> C[Prettier] B --> D[Errors Found?] D -->|Yes| E[Fix or Report] D -->|No| F[Pass] C --> G[Format Code] G --> H[Consistent Style] E --> I[CI Fails] F --> J[CI Passes]
ESLint Setup
npm init @eslint/config
Or install manually:
npm install --save-dev eslint
npx eslint --init
Expected Output
$ npx eslint --init
You can also run this command directly using 'npm init @eslint/config'.
Need to install the following packages:
@eslint/create-config
Ok to proceed? (y) y
? How would you like to use ESLint? ...
? What type of modules does your project use? JavaScript modules (import/export)
? Which framework does your project use? React
? Does your project use TypeScript? Yes
? Where does your code run? Browser
? What format do you want your config file to be in? JSON
ESLint Configuration
{
"env": {
"browser": true,
"es2021": true,
"node": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:"@typescript"-eslint/recommended]
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": ["react", "@typescript-eslint"],
"rules": {
"indent": ["error", 2],
"linebreak-style": ["error", "unix"],
"quotes": ["error", "single"],
"semi": ["error", "always"],
"no-unused-vars": "warn",
"no-console": "warn",
"react/react-in-jsx-scope": "off"
}
}
Running ESLint
# Lint a file
npx eslint src/index.js
# Lint with auto-fix
npx eslint src/index.js --fix
# Lint entire project
npx eslint src/ --ext .js,.jsx,.ts,.tsx
Expected Output
$ npx eslint src/index.js
/home/user/project/src/index.js
5:10 warning 'unusedVar' is defined but never used no-unused-vars
8:2 error Expected indentation of 2 spaces but found 4 indent
9:18 error Strings must use singlequote quotes
2 problems (2 errors, 1 warning)
1 error and 0 warnings potentially fixable with the `--fix` option.
Prettier Setup
npm install --save-dev prettier
Prettier Configuration
Create .prettierrc:
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all",
"printWidth": 100,
"bracketSpacing": true,
"arrowParens": "always",
"endOfLine": "lf"
}
Running Prettier
# Check formatting
npx prettier --check src/
# Format files
npx prettier --write src/
# Format with specific file types
npx prettier --write "src/**/*.{js,ts,jsx,tsx,css,json}"
Expected Output
$ npx prettier --check src/
Checking formatting...
src/index.js
src/utils.js
Code style issues found in 2 files. Run Prettier with --write to fix.
$ npx prettier --write src/
src/index.js 48ms
src/utils.js 32ms
ESLint and Prettier Together
ESLint and Prettier can conflict. Use eslint-config-prettier to disable ESLint rules that conflict with Prettier.
npm install --save-dev eslint-config-prettier
Update .eslintrc.json:
{
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:"@typescript"-eslint/recommended",
"prettier]
]
}
The prettier config must be last in extends to override conflicting rules.
Format-on-Save in VS Code
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"editor.formatOnSave": true,
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
Git Hooks with Husky
Prevent unformatted code from being committed.
npm install --save-dev husky lint-staged
npx husky init
Lint-Staged Configuration
{
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --fix",
"prettier --write]
],
"*.{css,json,md}": [
"prettier --write]
]
}
}
Husky Pre-commit Hook
# .husky/pre-commit
npx lint-staged
Expected Behavior
When you run git commit, Husky triggers lint-staged, which runs ESLint and Prettier on staged files only. If linting fails, the commit is prevented.
ESLint for TypeScript
npm install --save-dev @typescript-eslint/parser @typescript-eslint/eslint-plugin
{
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"rules": {
"@typescript-eslint/explicit-function-return-type": "warn",
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }]
}
}
CI/CD Integration
GitHub Actions
# .github/workflows/lint.yml
name: Lint
on: [pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx eslint src/ --max-warnings 0
- run: npx prettier --check src/
GitLab CI
lint:
stage: test
image: node:20
script:
- npm ci
- npx eslint src/ --max-warnings 0
- npx prettier --check src/
Common Errors
| Problem | Cause | Fix |
|---|---|---|
| ESLint and Prettier conflict | Both modify same formatting rules | Add prettier as the last item in ESLint's extends |
<a href="/compiler-design/syntax-analysis/">Parsing</a> error: Unexpected token |
ESLint not configured for JSX/TypeScript | Set parser: @<a href="/programming-languages/typescript/">TypeScript</a>-eslint/parser and enable jsx in parserOptions |
| Prettier breaks long lines unexpectedly | printWidth too small |
Increase printWidth in .prettierrc |
| Husky hooks not running | .git/hooks path mismatch |
Run npx husky install |
| ESLint fix changes too many files | Rules too aggressive | Use warn instead of error for style rules |
Practice Questions
1. What is the purpose of eslint-config-prettier?
It disables ESLint rules that conflict with Prettier's formatting.
2. How do you auto-fix ESLint issues from the command line?
npx eslint --fix <file>.
3. What does lint-staged do in combination with Husky?
It runs linters only on staged files (files about to be committed), preventing unformatted code from entering the Repository.
4. How do you check if Prettier would change any files without actually modifying them?
npx prettier --check src/.
5. What is the purpose of the --max-warnings 0 flag in ESLint CI commands?
It treats warnings as errors, causing CI to fail if any warnings exist.
Challenge
Create a complete ESLint and Prettier setup for a TypeScript + React project. Add Husky pre-commit hooks with lint-staged. Configure ESLint with TypeScript rules, React rules, and import ordering. Add a GitHub Actions workflow that runs linting on every Pull Request.
Real-World Task
Take an existing JavaScript or TypeScript project without linting. Initialize ESLint and Prettier, run the initial fix, and resolve all remaining lint errors. Set up format-on-save in your editor. Configure Husky to prevent unformatted commits. Create a CI workflow that runs the linter on pull requests.
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro