# Prettier and ESLint-Automating Code Style and Quality

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:

```json
{
  "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:

```bash
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:

```javascript
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:

```bash
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`:

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

Add the following to `.eslintrc.js`:

```javascript
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)

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

### .eslintrc.js (ESLint Configuration)

```javascript
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:

```bash
npm install --save-dev husky lint-staged
```

Add the following to `package.json`:

```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`:

```javascript
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`:

```javascript
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:

```bash
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`:

```javascript
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:

```javascript
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:

```javascript
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:

```javascript
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:

```yaml
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
```
