36
Enforce Husky Pre-Commit With ESLint & Prettier In Monorepo
Okay, this kept me frustrated for a whole week because I suck at configurations at many levels. But thankfully, I've now closed my 16 chrome tabs and writing this out to make sure you don't have to face the same exact problem.
When different developers work on the same codebase, it becomes necessary to enforce some rules to keep code in check. ESLint and Prettier go hand in hand for this purpose in most of JS projects and integration support is widely available.
Finally husky is library that allows us trigger actions before committing or pushing. It provides git hooks for this purpose. I'll navigate it to in a minute.
The problem that I faced here was that my project was built like a monorepo. It has frontend, backend and library folders in it. In order to use husky git hooks, they are to be placed in the directory where git is placed.
But then again, for husky to work, it needs to utilize package.json file. This issue had me rolling for days.
I'll navigate step by step from installing husky to committing the code. This might takes quite a few commands, so please bear with me.
In the root folder of the repo where git resides, run following commands:
npx husky install
npx husky add .husky/pre-commit "npm test"
This will create a .husky
folder in the root directory with pre-commit
file in it. This file would have a single command npm test in it.
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npm test
Let's leave it for now and move to next step.
Go to your frontend project and install eslint, husky and prettier with the following commands:
npm install husky lint-staged eslint-plugin-prettier eslint-config-prettier --save-dev
npm install --save-dev --save-exact prettier
--save-dev
keeps these libraries in devDependencies
because they won't be used in production and are here for development only.
We'll be creating few files to let our linters know how they would be working across the project.
- Create
.estlintignore
and.prettierignore
files and place the following code
build
node_modules
.github
This will inform our linters not to look into files in the above mentioned directories
- Now we'll be adding few configurations for estlint. Create a file
.eslintrc.js
with this code:
module.exports = {
env: {
browser: true,
es6: true,
},
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:prettier/recommended',
'plugin:jsx-a11y/strict',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 2018,
sourceType: 'module',
},
plugins: ['react', 'jsx-a11y', '@typescript-eslint'],
rules: {
'react-hooks/exhaustive-deps': 'error',
'no-var': 'error',
'brace-style': 'error',
'prefer-template': 'error',
radix: 'error',
'space-before-blocks': 'error',
'import/prefer-default-export': 'off',
},
overrides: [
{
files: [
'**/*.test.js',
'**/*.test.jsx',
'**/*.test.tsx',
'**/*.spec.js',
'**/*.spec.jsx',
'**/*.spec.tsx',
],
env: {
jest: true,
},
},
],
};
- And finally the configuration for prettier. Add a file
.prettierrc.js
and put the following code:
module.exports = {
printWidth: 100,
tabWidth: 2,
singleQuote: true,
semi: true,
trailingComma: 'all',
arrowParens: "always",
overrides: [
{
files: '*.{js,jsx,tsx,ts,scss,json,html}',
options: {
tabWidth: 4,
},
},
],
};
We're almost there and now we'll have to add few scripts to package.json. I'll guide you about their purpose along the way.
- Add the following line in the scripts section:
"prepare": "cd .. && husky install frontend/.husky"
npm prepare
command runs before we commit our code. What essentially we're doing here is that we are moving out of frontend directory and installing husky in the front-end. - Now we need to add our linting configuration governed by
lint-staged
. Place the following code after scripts section:
"lint-staged": {
"*.{js,ts,tsx, jsx}": [
"eslint --quiet --fix"
],
"*.{json,md,html,js,jsx,ts,tsx}": [
"prettier --write"
]
},
We've written the extensions of the files eslint and prettier would be amending.
Finally, we'll be adding a script that would invoke linting. Add this line in your scripts:
"lint-front": "lint-staged"
Runningnpm run lint-front
would trigger linting our application.Let's just inform our husky to run
npm run lint-front
before commit. Go to the husky folder in the project root and replace pre-commit file with this code:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
cd frontend
npm run lint-frontend
If everything followed correctly, making a commit would trigger linting. That's the end of it. Hope this helps someone. If you are still having issue, do mention the comments. I'd be more than happy to help.
36