Prettier and ESLint-Automating Code Style and Quality

Tianya SchoolTianya School
5 min read

Prettier and ESLint are complementary tools that together ensure code style consistency and quality. Prettier handles code formatting, while ESLint performs more complex static analysis and rule checking.

Prettier

Purpose

  • Automates code formatting, ensuring consistent indentation, brackets, quotes, and line breaks.

  • Requires minimal configuration, as Prettier has a default code style.

  • Supports multiple programming languages, including JavaScript, TypeScript, CSS, HTML, and more.

  • Can be integrated with ESLint to avoid rule conflicts.

Usage Example

Create a .prettierrc or .prettierrc.json file in the project root to configure Prettier, for example:

{
  "printWidth": 80, // Line width
  "tabWidth": 2, // Tab width
  "useTabs": false, // Use spaces instead of tabs
  "semi": true, // Use semicolons
  "singleQuote": true, // Use single quotes
  "trailingComma": "all", // Trailing commas
  "bracketSpacing": true, // Spaces inside object braces
  "jsxBracketSameLine": false // JSX closing bracket on a new line
}

Install Prettier in your project:

npm install --save-dev prettier

Add Prettier-generated temporary files to .gitignore.

ESLint

Purpose

  • Static code analysis to detect potential errors, code smells, and discouraged programming practices.

  • Offers extensive customizable rules to check code style, variable usage, code complexity, and more.

  • Can be integrated with Prettier to format code first and then perform checks, avoiding format-related issues.

Usage Example

Create an .eslintrc.js or .eslintrc.yaml configuration file:

module.exports = {
  env: {
    browser: true,
    es2021: true,
  },
  extends: [
    'plugin:react/recommended',
    'airbnb-base',
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaVersion: 12,
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true,
    },
  },
  plugins: [
    '@typescript-eslint',
    'react',
  ],
  rules: {
    'no-console': 'off', // Disable no-console rule
    'import/no-unresolved': 'error', // Report unresolved imports
  },
};

Install ESLint and related plugins:

npm install --save-dev eslint eslint-plugin-react @typescript-eslint/parser @typescript-eslint/eslint-plugin

Use npx eslint or configure an IDE (e.g., VSCode) with the ESLint plugin for real-time checks.

Integration and Automation

Integrate Prettier with ESLint using eslint-plugin-prettier and eslint-config-prettier:

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

Add the following to .eslintrc.js:

module.exports = {
  // ...
  plugins: ['prettier'],
  extends: ['plugin:prettier/recommended'], // Use Prettier's ESLint rules
  rules: {
    'prettier/prettier': 'error', // Treat Prettier rules as errors
    // ...other rules
  },
};

Now, running eslint --fix will first apply Prettier formatting and then perform ESLint checks.

Example Configuration Files

.prettierrc (Prettier Configuration)

{
  "semi": true,
  "trailingComma": "none",
  "tabWidth": 2,
  "singleQuote": true,
  "printWidth": 120,
  "jsxSingleQuote": true,
  "arrowParens": "avoid",
  "htmlWhitespaceSensitivity": "css",
  "endOfLine": "lf"
}

.eslintrc.js (ESLint Configuration)

module.exports = {
  env: {
    browser: true,
    es6: true,
  },
  extends: [
    'airbnb-base',
    'plugin:@typescript-eslint/recommended',
    'plugin:prettier/recommended',
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaVersion: 2020,
    sourceType: 'module',
  },
  plugins: ['@typescript-eslint', 'prettier'],
  rules: {
    'prettier/prettier': 'error',
    'no-unused-vars': 'warn',
    'no-console': 'warn',
  },
};

Integration into Build Process

Using Husky and lint-staged for Pre-Commit Checks

Install dependencies:

npm install --save-dev husky lint-staged

Add the following to package.json:

"husky": {
  "hooks": {
    "pre-commit": "lint-staged"
  }
},
"lint-staged": {
  "*.ts?(x)": ["prettier --write", "eslint --fix"],
  "*.js?(x)": ["prettier --write", "eslint --fix"],
  "*.html": ["prettier --write"],
  "*.css": ["prettier --write"]
}

This ensures that lint-staged runs Prettier and ESLint to format and fix code before each commit.

IDE Configuration

In Visual Studio Code, WebStorm, or other IDEs supporting ESLint and Prettier, install the corresponding plugins and configure automatic formatting and linting.

Custom Rules

ESLint's flexibility allows you to create custom rules to meet specific project needs. Add custom rules in .eslintrc.js:

rules: {
  'your-custom-rule': 'error',
  // ...
}

Create a lib or rules directory and define your custom rule modules there.

Common Issues and Solutions

Conflict Resolution

Sometimes, Prettier and ESLint rules may conflict. In such cases, prioritize Prettier's rules for formatting. If specific ESLint rules are needed, disable conflicting Prettier rules in .eslintrc.js:

rules: {
  'prettier/prettier': ['error', { singleQuote: false }] // Disable Prettier's single quote rule
}

Performance Optimization

If ESLint runs slowly, consider these optimizations:

  • Run only when necessary: For example, run only after relevant files are modified.

  • Use the --cache option: ESLint caches checked files to speed up subsequent runs.

  • Use .eslintignore: Exclude files and directories that don’t need checking.

Using ESLint Plugins and Shared Configurations

Plugins

  • @typescript-eslint: Provides additional rules and fixes for TypeScript.

  • eslint-plugin-import: Checks import order and export standards.

  • eslint-plugin-react: Specific rules for React components.

  • eslint-plugin-react-hooks: Checks React Hooks usage.

  • eslint-plugin-prettier: Ensures ESLint works seamlessly with Prettier.

Install these plugins:

npm install --save-dev eslint-plugin-import eslint-plugin-react eslint-plugin-react-hooks @typescript-eslint/eslint-plugin

Shared Configurations

  • eslint-config-airbnb: Airbnb's coding style guide.

  • eslint-config-prettier: Disables ESLint rules that conflict with Prettier.

Use shared configurations in .eslintrc.js:

module.exports = {
  extends: [
    'airbnb',
    'airbnb-typescript',
    'plugin:@typescript-eslint/recommended',
    'plugin:import/recommended',
    'plugin:react/recommended',
    'plugin:react-hooks/recommended',
    'plugin:prettier/recommended',
  ],
  // ...
};

Customizing Shared Configurations

Customize shared configurations based on project needs:

module.exports = {
  extends: [
    'airbnb',
    'airbnb-typescript',
    'plugin:@typescript-eslint/recommended',
    'plugin:import/recommended',
    'plugin:react/recommended',
    'plugin:react-hooks/recommended',
    'plugin:prettier/recommended',
  ],
  rules: {
    'import/prefer-default-export': 'off', // Disable warnings for non-default exports
    '@typescript-eslint/explicit-module-boundary-types': 'off', // Disable type declaration warnings
    // Add or modify other rules
  },
};

Advanced Usage

Configuring Environments

Set environment variables in .eslintrc.js to enable rules for specific environments:

env: {
  browser: true,
  es6: true,
  node: true,
  jest: true,
}

Using ESLint’s overrides Field

The overrides field allows you to specify different rules for specific file types or directories. For example, add separate rules for .test.js files:

module.exports = {
  overrides: [
    {
      files: ['**/*.test.js'],
      rules: {
        'no-unused-expressions': 'off', // Disable unused expression warnings in test files
      },
    },
  ],
  // ...
};

Deployment to Continuous Integration (CI)

Integrate ESLint and Prettier into the CI pipeline to ensure all committed code meets standards. For example, configure in GitHub Actions:

name: Lint and Format

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Setup Node.js
      uses: actions/setup-node@v2
      with:
        node-version: '14.x'
    - name: Install dependencies
      run: npm ci
    - name: Lint and format
      run: npm run lint
0
Subscribe to my newsletter

Read articles from Tianya School directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Tianya School
Tianya School

❤️ • Full Stack Developer 🚀 • Building Web Apps 👨‍💻 • Learning in Public 🤗 • Software Developer ⚡ • Freelance Dev 💼 • DM for Work / Collabs 💬