Sitemap
Sachin Patel

Sachin Patel

Senior Software Engineer | Frontend specialist | Building scalable web apps & optimizing UX | Sharing insights on modern web technologies. More: sachinp.com

Prevent Build-Time Errors: Using Husky to Run ESLint on Staged Files

4 min readFeb 24, 2025

--

Linting issues can slow down development, often surfacing during builds or CI/CD runs. Catching them earlier saves time and improves workflow efficiency, reducing unnecessary debugging efforts.

Press enter or click to view image in full size
Photo by Jack Dong on Unsplash

Introduction

Using Husky to run ESLint on staged files before committing ensures code quality and consistency. Husky enables Git hooks, letting us run scripts before commits. Combined with lint-staged, only staged files get linted, optimizing performance and reducing unnecessary computations.

This guide walks through setting up Husky to automatically lint staged files using ESLint, preventing errors from entering the repository and ensuring cleaner commits.

What is Husky?

Before diving into the setup, let’s first explore Husky and its capabilities. Husky is a Git hook tool that automates tasks before commits and pushes, ensuring code quality and consistency. Apart from running ESLint on staged files, it can:

  • Run Tests Before Commit — Prevents broken code by executing unit or integration tests.
  • Enforce Code Formatting — Runs Prettier or other formatters to maintain style consistency.
  • Prevent Bad Commits — Blocks commits with linting errors, security vulnerabilities, or missing dependencies.
  • Automate Dependency Checks — Ensures packages are installed before committing or pushing.
  • Enforce Commit Message Standards — Uses commitlint to maintain a structured commit history.

Step 1: Install Dependencies

To begin, install Husky and lint-staged as development dependencies:

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

These tools enforce linting rules at pre-commit, ensuring only formatted, error-free code gets committed, thus reducing the number of build-time failures.

Step 2: Enable Husky in the Project

Initialize Husky by running the following command:

npx husky install

This creates the .husky/ directory, which will store all Git hooks configured for the repository.

Step 3: Configure Husky Pre-Commit Hook

If you have already executed npx husky install, a pre-commit hook might already exist in the .husky/ directory, containing npm test as its default content. To modify it for linting staged files, replace its content with the following:

File: .husky/pre-commit

npm run lint-staged

This command ensures that lint-staged runs whenever you attempt to commit changes.

To make sure the pre-commit script runs correctly, grant execution permissions:

chmod ug+x .husky/*

Step 4: Set Up Lint-Staged

4.1 Configuring package.json

Understanding the prepare Script

The prepare script in package.json ensures that Husky is correctly installed and configured, but it also includes a conditional check:

{
...
"prepare": "node -e \"if (process.env.NODE_ENV !== 'production'){process.exit(1)} \" || husky install | chmod ug+x .husky/*"
}

Breakdown:

  1. Check Environment: The node -e command runs an inline Node.js script to check if NODE_ENV is set to production. If it's not, the script exits with a failure status (1).
  2. Install Husky: The || operator ensures that if the previous command fails, husky install runs, setting up Git hooks.
  3. Ensure Execution Permissions: The | chmod ug+x .husky/* command ensures that Husky scripts are executable.

This setup prevents Husky from running in production environments while maintaining proper permissions for pre-commit hooks.

Inside your package.json, define a script for running lint-staged:

Get Sachin Patel’s stories in your inbox

Join Medium for free to get updates from this writer.

File: package.json

{
"scripts": {
"lint-staged": "lint-staged",
"prepare": "node -e \"if (process.env.NODE_ENV !== 'production'){process.exit(1)} \" || husky install | chmod ug+x .husky/*"
}
}

This ensures that Husky is correctly installed and configured.

4.2 Configuring .lintstagedrc.json

Define which files should be linted using a lint-staged configuration file:

File: .lintstagedrc.json

{
"*.{js,tsx,ts}": ["eslint --ignore-path .gitignore --fix", "eslint --ignore-path .gitignore"]
}

This configuration ensures that JavaScript and TypeScript files are automatically formatted and checked before being committed.

Alternatively, if you’re working with Next.js, you can use a .lintstagedrc.js configuration for lint-staged.

Configuring .lintstagedrc.js

If you’re not using the Next.js, you can skip this configuration.

File: .lintstagedrc.js

// Ref: https://nextjs.org/docs/pages/api-reference/config/eslint#running-lint-on-staged-files

const path = require('path');

const buildEslintCommand = (filenames) =>
`next lint --fix --file ${filenames.map((f) => path.relative(process.cwd(), f)).join(' --file ')}`;

module.exports = {
'*.{js,jsx,ts,tsx}': [buildEslintCommand],
};

This setup allows Next.js projects to run next lint only on staged files, optimizing performance.

Step 5: Testing the Setup

To verify everything works correctly, follow these steps:

1. Stage a file for commit:

To produce ESLint error, you can import any component (from your repo) in a file and keep it unused.

git add yourfile.js

2. Attempt to commit:

git commit -m "Test Husky linting"

3. Check if ESLint runs on staged files:

  • If linting errors exist, the commit will be blocked until the issues are fixed.
  • If no errors exist, the commit will proceed.

Step 6: Troubleshooting

If you run into issues, try the following troubleshooting steps:

  • Ensure Husky is installed:
npx husky install
  • Check if the .husky/pre-commit script has execution permissions:
ls -l .husky/
  • Manually run lint-staged to debug errors:
npx lint-staged
  • If you are using Next.js, confirm that the correct ESLint configuration is being picked up.

Conclusion

Setting up Husky with ESLint and lint-staged helps enforce code quality by catching linting errors before they reach the repository. This ensures that only properly formatted, error-free code gets committed, improving overall project maintainability and developer productivity.

By integrating this workflow into your project, you can prevent build-time errors and maintain a consistent coding standard across your team.

Further Reading

Happy coding! 🚀

--

Sachin Patel
Sachin Patel

Written by Sachin Patel

Senior Software Engineer | Frontend specialist | Building scalable web apps & optimizing UX | Sharing insights on modern web technologies. More: sachinp.com