Share
1

Linters and Formatters: ESLint, Prettier, and Integration for Code Quality

by ObserverPoint · July 26, 2025

In software development, maintaining consistent code style and ensuring code quality across a team is paramount. This is where linters and formatters come into play. They are automated tools that help enforce coding standards, catch potential errors early, and improve code readability and maintainability. This article will explore two of the most popular tools in the JavaScript ecosystem—ESLint for code quality and Prettier for code formatting—and demonstrate how to integrate them into your development workflow using VS Code and Git hooks with Husky.


1. Introduction to Linters and Formatters

1.1. Linters (e.g., ESLint)

A linter is a tool that analyzes source code to flag programming errors, bugs, stylistic errors, and suspicious constructs. It helps developers adhere to a set of predefined rules that contribute to code quality and consistency.

  • Focus: Code quality, potential bugs, best practices, stylistic issues that might lead to errors.
  • Example Rule: “Variables should not be declared but never used,” “No unreachable code,” “Use strict equality (===) instead of loose (==).”

1.2. Formatters (e.g., Prettier)

A formatter is a tool that automatically restructures code according to a set of predefined style rules. Its primary goal is to ensure a consistent code style across an entire codebase, regardless of who wrote the code.

  • Focus: Code style, indentation, line endings, semi-colons, single vs. double quotes, maximum line length, bracket placement.
  • Benefit: Eliminates bikeshedding over style, frees up developers to focus on logic.

2. ESLint for Code Quality

ESLint is the most widely used linting tool for JavaScript and JSX. It’s highly configurable, allowing you to define your own rules or extend popular configurations (e.g., Airbnb, Google, Create React App’s defaults).

2.1. Basic ESLint Setup:

  1. Installation: Install ESLint and relevant plugins (e.g., for React, TypeScript) as dev dependencies.
    npm install eslint --save-dev
    # For React projects with TypeScript:
    npm install eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-plugin-react --save-dev

  2. Configuration (`.eslintrc.json` or `.eslintrc.js`): Run `npx eslint –init` to generate a basic configuration file, or create it manually.
    // .eslintrc.json (example for React with TypeScript)
    {
    "env": {
    "browser": true,
    "es2021": true,
    "jest": true, // If using Jest for testing
    "node": true
    },
    "extends": [
    "eslint:recommended",
    "plugin:react/recommended", // React specific rules
    "plugin:@typescript-eslint/recommended", // TypeScript specific rules
    "plugin:react/jsx-runtime" // For React 17+ JSX transform
    ],
    "parser": "@typescript-eslint/parser",
    "parserOptions": {
    "ecmaFeatures": {
    "jsx": true
    },
    "ecmaVersion": "latest",
    "sourceType": "module"
    },
    "plugins": [
    "react",
    "@typescript-eslint"
    ],
    "rules": {
    // Custom rules or overrides
    // "indent": ["error", 2], // Enforce 2 space indentation (often handled by Prettier)
    "linebreak-style": ["error", "unix"],
    "quotes": ["error", "single"],
    "semi": ["error", "always"],
    "react/react-in-jsx-scope": "off", // Not needed with React 17+ JSX transform
    "@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }], // Warn on unused vars, ignore args starting with _
    "no-console": "warn" // Warn on console.log
    },
    "settings": {
    "react": {
    "version": "detect" // Automatically detect the React version
    }
    },
    "ignorePatterns": ["node_modules/", "build/", "dist/"] // Files/folders to ignore
    }

  3. Running ESLint: Add a script to `package.json`:
    // package.json
    "scripts": {
    "lint": "eslint \"{src,apps,libs}/**/*.ts,{src,apps,libs}/**/*.tsx\"",
    "lint:fix": "eslint \"{src,apps,libs}/**/*.ts,{src,apps,libs}/**/*.tsx\" --fix"
    }

    Run `npm run lint` to check or `npm run lint:fix` to auto-fix some issues.

3. Prettier for Code Formatting

Prettier is an opinionated code formatter that enforces a consistent style by parsing your code and re-printing it with its own rules. It eliminates bikeshedding over style and ensures all code looks the same.

3.1. Basic Prettier Setup:

  1. Installation: Install Prettier as a dev dependency.
    npm install prettier --save-dev

  2. Configuration (`.prettierrc.json` or `.prettierrc` file):
    // .prettierrc.json
    {
    "trailingComma": "es5",
    "tabWidth": 2,
    "semi": true,
    "singleQuote": true,
    "printWidth": 100,
    "arrowParens": "always",
    "endOfLine": "lf"
    }

  3. Running Prettier: Add a script to `package.json`:
    // package.json
    "scripts": {
    "format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,json,css,scss,md}\""
    }

    Run `npm run format` to format your files.

ESLint + Prettier Integration: To make ESLint and Prettier work together without conflicts (where Prettier formats, and ESLint then complains about the formatting), you need to install specific ESLint plugins:

npm install eslint-config-prettier eslint-plugin-prettier --save-dev
    

Then, add `”plugin:prettier/recommended”` to your `.eslintrc.json`’s `extends` array, usually as the last item to override any conflicting rules:

// .eslintrc.json (excerpt)
"extends": [
    "eslint:recommended",
    "plugin:react/recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:react/jsx-runtime",
    // highlight-start
    "plugin:prettier/recommended" // MUST BE THE LAST EXTENSION
    // highlight-end
],
    

4. Integrating with VS Code

Seamless integration with your IDE (especially VS Code) is key for a smooth development experience. This allows linting and formatting errors to appear directly in your editor and can even fix them automatically.

4.1. VS Code Extensions:

4.2. Recommended VS Code Settings (`settings.json`):

To automate formatting and linting fixes on save, add or update these settings in your VS Code `settings.json` (File > Preferences > Settings or Code > Preferences > Settings, then click the curly braces icon):

```json
{
    "editor.formatOnSave": true,
    // Set Prettier as the default formatter for relevant languages
    "[javascript]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "[javascriptreact]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "[typescript]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "[typescriptreact]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "[json]": { // Also format JSON files
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "[css]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "[scss]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    // Enable ESLint auto-fix on save
    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": "explicit" // Or true
    },
    // ESLint specific settings
    "eslint.run": "onSave",
    "eslint.probe": [
        "javascript",
        "javascriptreact",
        "typescript",
        "typescriptreact"
    ],
    "eslint.validate": [
        "javascript",
        "javascriptreact",
        "typescript",
        "typescriptreact"
    ]
}
```
    

With these settings, every time you save a file, Prettier will format it, and then ESLint will run, attempting to fix any remaining autofixable issues. This creates a highly efficient and consistent workflow.


5. Integrating with Git Hooks (Husky)

While VS Code integration is great for development time, Git hooks provide an additional layer of assurance by running linting and formatting checks automatically before commits or pushes. This prevents improperly formatted or low-quality code from even entering your repository. Husky is a popular npm package that makes it easy to manage Git hooks.

5.1. Benefits of Git Hooks:

  • Prevent Bad Commits: Ensure only linted and formatted code is committed.
  • Team Consistency: Guarantees that all team members adhere to standards, regardless of their IDE setup.
  • CI/CD Efficiency: Reduces failures in CI/CD pipelines due to style or basic quality issues.

5.2. Husky Setup with `lint-staged`:

Often, you only want to lint/format the files that are being committed, not the entire project. This is where `lint-staged` comes in handy.

  1. Install Husky and `lint-staged`:
    npm install husky lint-staged --save-dev

  2. Configure Husky: Add a prepare script to `package.json` and initialize Husky.
    // package.json
    "scripts": {
    "prepare": "husky" // For Husky v9+
    },

    Then run `npm run prepare` (or `yarn prepare`, `pnpm prepare`). This will create the `.husky/` directory.
  3. Add a `pre-commit` hook: Create a `pre-commit` file in the `.husky/` directory.
    npx husky add .husky/pre-commit "npm test" // Example if you want to run tests
    npx husky add .husky/pre-commit "npx lint-staged" // Run lint-staged before commit

  4. Configure `lint-staged` in `package.json`: This tells `lint-staged` which commands to run on which files.
    // package.json
    "lint-staged": {
    "src/**/*.{js,jsx,ts,tsx}": [
    "eslint --fix", // Auto-fix ESLint issues
    "prettier --write" // Format with Prettier
    ],
    "src/**/*.{json,css,scss,md}": [
    "prettier --write" // Format non-code files
    ]
    },

Now, every time you run `git commit`, Husky will trigger `lint-staged`, which in turn will run ESLint (with auto-fix) and Prettier on only the staged files. If any linting errors cannot be fixed automatically, or if formatting fails, the commit will be aborted, forcing you to address the issues before committing.

By implementing ESLint, Prettier, and integrating them with VS Code and Git hooks, you establish a robust and automated system for maintaining high code quality and consistency across your React projects and development team.


References

You may also like