Getting Started with ESLint and Husky in Your Node.js Project
Published: 2024-05-26 04:29:39

Ensuring clean and consistent code is crucial for any Node.js project. This blog dives into a practical approach to achieve that by integrating ESLint with Husky. It guides you through setting up pre-commit linting, a powerful technique that automatically checks your code for style and formatting issues before every commit. With this setup, you can streamline your development process and maintain a high level of code quality throughout your project.

To integrate ESLint with a pre-commit hook using Husky in your Node.js project, follow these steps:

## 1. Install Dependencies

You'll need ESLint, Husky, and lint-staged. You can install them using npm or yarn. Here is how you can do it with npm:

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

## 2. Initialize ESLint

If you haven't already set up ESLint, you can initialize it in your project by running:

```
npx eslint --init
```


This command will guide you through a series of questions to set up ESLint according to your project's needs.

```
You can also run this command directly using 'npm init @eslint/config@latest'.
Need to install the following packages:
@eslint/create-config@1.1.1
Ok to proceed? (y) y
✔ How would you like to use ESLint? · problems
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · react
✔ The React plugin doesn't officially support ESLint v9 yet. What would you like to do? · 9.x
✔ Does your project use TypeScript? · typescript
✔ Where does your code run? · browser
The config that you've selected requires the following dependencies:

eslint@9.x, globals, @eslint/js, typescript-eslint, eslint-plugin-react, @eslint/compat
✔ Would you like to install them now? · No / Yes
✔ Which package manager do you want to use? · npm
☕️Installing...
npm WARN using --force Recommended protections disabled.
```


## 3. Configure Husky

Starting with Husky v7, you need to configure Husky using husky commands and add hooks manually. First, initialize Husky:

```
npm install --save-dev husky
```

> If you face an error message `npm ERR! ERESOLVE could not resolve` error you're encountering when installing Husky, then follow Resolving the Conflict:

> Here are two approaches you can take:

> ### 1. Downgrade eslint:

> This approach aligns your eslint version with the requirements of eslint-plugin-react.
Run the following command to downgrade eslint to a compatible version (e.g., 8.22.0):

> ```
> npm install --save-dev eslint@8.22.0
> ```

> ### 2. Use --legacy-peer-deps (Cautionary Approach):

> This approach forces the installation but might lead to compatibility issues in the future. Use it with caution if downgrading isn't feasible.
Run the following command, but be aware of potential risks:

> ```
> npm install --save-dev husky --legacy-peer-deps
> ```

> After resolving the conflict:

> Re-run the original command to install husky:

```
npm install --save-dev husky
```


> ### Choosing the Best Approach:

> 1. Downgrading eslint is generally the recommended approach as it ensures compatibility and avoids potential issues. Check  the documentation of the other packages in your project to  ensure they are compatible with eslint@8.22.0.
> 2. Using --legacy-peer-deps should be a last resort. It might > lead to unexpected behavior or errors if the peer > dependencies are not truly compatible.  


## 4. Initialize Husky

```
npx husky init
```

This will automatically configure Husky and add a basic .husky/pre-commit file (you can customize this later).

- Choose a configuration style (I recommend "JavaScript Standard Style").

- Select the features you want to enable/disable based on your project's needs.

This creates an `.eslintrc.json` file in your project root, which defines ESLint rules.

```
cat eslint.config.mjs
import globals from "globals";
import pluginJs from "@eslint/js";
import tseslint from "typescript-eslint";
import pluginReactConfig from "eslint-plugin-react/configs/recommended.js";
import { fixupConfigRules } from "@eslint/compat";


export default [
  {languageOptions: { globals: globals.browser }},
  pluginJs.configs.recommended,
  ...tseslint.configs.recommended,
  ...fixupConfigRules(pluginReactConfig),
];
```


## 5. Add Pre-commit Script (Optional):


It's time to create Husky Pre-commit Hook. In your package.json, add a husky section under scripts:

```
{
  "scripts": {
    "precommit": "eslint ."
  }
}
```

This tells Husky to run eslint . (lint all files) before every git commit.

So, your final package.json will look like:

```
{
  "devDependencies": {
    "@eslint/compat": "^1.0.1",
    "@eslint/js": "^9.3.0",
    "eslint": "^8.22.0",
    "eslint-plugin-react": "^7.34.1",
    "globals": "^15.2.0",
    "husky": "^9.0.11",
    "lint-staged": "^15.2.2",
    "typescript-eslint": "^7.9.0"
  },
  "scripts": {
    "prepare": "husky"
    "precommit": "eslint ."
  }
}
```

## 6.  Test Pre-commit Hook

- Create a file (e.g., test.js) with intentional linting errors (like missing semicolons).
- Try to commit your changes. Husky should prevent the commit and display ESLint errors.

## Conclusion

By following these steps, you ensure that your code is linted before every commit, maintaining code quality and consistency. If there are any linting errors, the commit will be blocked until they are resolved.