What is husky?
Husky is a JavaScript package that allows you to run some code during various parts of your git workflow. Husky leverages git hooks to allow you to hook into various git events such as pre-commit and pre-push.
What is lint-staged?
Lint-staged allows you to run code against your staged git files to automate the tedious part of your workflows, such as formatting with Prettier and/or linting with ESLint.
Using husky with lint-staged
You can use husky to trigger lint-staged during the pre-commit hook, so that your coding standards are enforced right as you commit. The major benefit of this is it enforces your coding standards without someone needing to configure and install certain extensions in their IDE to enforce them on save or remembering to do anything. Your code gets fixed before it ever leaves your machine, so you don’t have to wait for your CI to inform you that you forgot to run the formatter or linter.
The Problem: husky expects your package.json at the root
The problem is, husky expects your package.json to be at the root of your project. That’s a fine assumption to make a lot of times, but sometimes we might be in more of a monorepo situation, or where a single repo contains both the Server and Client in separate folders.
The Solution
I’m going to use the example from the default React and ASP.NET Core template when you run dotnet new react. The default folder structure has the React code nested under a /ClientApp folder with the corresponding package.json. The folder structure looks like this:
Let’s dive into the steps. You can view the completed repo here.
cdinto the directory with yourpackage.json- In my case:
./ClientApp
- In my case:
- Install husky and lint-staged:
npm i husky lint-staged -D
- Add a “prepare” npm script to your
package.jsonwith the following contents (note: the initialcdgoes to the repo root and thehusky installgoes from the repo root down to your directory with thepackage.json):
{
"scripts": {
// other scripts omitted
"prepare": "cd ../ && husky install ./ClientApp/.husky"
}
}
- Run
npm install
- FYI – a
.huskyfolder will appear in the same path as yourpackage.json, in my case under./ClientApp
- Create a
pre-commitfile with no file extension under the.huskyfolder with the following contents (note: the./ClientAppis the path to yourpackage.jsonrelative to the root of your repository):
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
cd ./ClientApp && npx lint-staged
- Make sure the
pre-commitfile is executable viachmod:
chmod +x ./.husky/pre-commit
- Add a
.lintstagedrcfile under your ./ClientApp folder (or wherever yourpackage.jsonlives) with the following contents:
{
"*.{js,ts,tsx,scss,css,md}": ["eslint", "prettier --write"]
}
As you can probably guess, the above says look for any changes to any of the file extensions defined on the left, and run the commands in the array on the right if you find any changes to those files.
And that’s it! Now if you try to make a commit, you will see that eslint and prettier will run and fix themselves as you would expect. See an example of it in action below:
