Hi everyone ! This article will show you how you can setup a Yarn monorepo to work with Husky.
Source code π¦ : https://github.com/0x2A-git/husky-yarn-monorepo-tutorial/tree/main
Goal β½
We are going to take a common example where we'd like to automatically lint all of our staged changes (regardless of their workspace) when committing using ESLint & Prettier.
Project structure ποΈ
.
|-- apps/
| app/
| ...
| package.json
|-- packages/
| package/
| ...
| package.json
`-- package.json
Monorepo Setup π§
First, upgrade yarn to the latest stable version and add workspace-tools plugin :
$ yarn set version stable
$ yarn
$ yarn plugin import workspace-tools
Note : If you don't want to use PnP and stick with node_modules run yarn config set nodeLinker node-modules
Once it is done, install Husky as a dependency of your whole monorepo :
$ yarn add -D husky
$ yarn run husky install
Then open your monorepo's package.json and add the following scripts :
{
"name": "husky-yarn-monorepo",
"packageManager": "yarn@3.5.1",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"private": true,
"workspaces": ["apps/*", "packages/*"],
"devDependencies": {
"husky": "^8.0.3"
},
"scripts": {
"postinstall": "husky install",
"pre-commit": "yarn workspaces foreach run pre-commit"
}
}
The pre-commit script will run a script called pre-commit script in every app & package package.json.
Now we are going to register the pre-commit script to Husky :
$ yarn run husky add .husky/pre-commit "yarn run pre-commit"
Next stage the file :
$ git add .husky/pre-commit
App / Package Setup π§
For the tutorial convenience the app and the package will have the same architecture. This part assumes that you've already setup your workspaces (yarn init, yarn, ...). Let's cd in one of the apps or the packages and follow these steps :
Setup Linting :
First install these dependencies :
$ yarn add -D eslint @typescript-eslint/eslint-plugin eslint-config-prettier eslint-config-standard-with-typescript eslint-plugin-import eslint-plugin-n eslint-plugin-prettier eslint-plugin-promise lint-staged prettier
Then create these files :
$ touch .eslintrc.js .lintstagedrc .prettierrc
Copy the following content in .eslintrc.js :
const path = require('path')
module.exports = {
env: {
es2021: true,
},
extends: ['standard-with-typescript', 'prettier'],
parserOptions: {
project: path.join(__dirname, '/tsconfig.json'),
ecmaVersion: 'latest',
sourceType: 'module',
},
overrides: [],
}
Configure lint-staged through the .lintstagedrc file :
{
"*.ts": ["eslint --fix", "prettier --write"]
}
In .prettierrc you can add this default configuration :
{
"trailingComma": "es5",
"tabWidth": 4,
"semi": false,
"singleQuote": true
}
Setup Typescript
Run these commands :
$ yarn add -D typescript
$ mkdir src
$ touch src/index.ts tsconfig.json
You can use this config in your tsconfig.json :
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"sourceMap": true,
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"baseUrl": "./src",
"outDir": "./dist",
"declaration": true,
},
"include": ["./**/**.ts"]
}
Setup pre-commit π
Add the following script in your app's or package's package.json :
...
"scripts": {
"pre-commit": "lint-staged"
}
...
You can copy the following code in src/index.ts :
const myFunction = () => {
return "This my function !"
}
myFunction()
Now let's try to commit our files by running :
$ git add -A
$ git commit -m "My commit message"
Note : If you get Usage Error: Couldn't find a script named "pre-commit". don't forget to implement pre-commit script in every app / package package.json.
After running the command you should get this error :
1:20 error Missing return type on function @typescript-eslint/explicit-function-return-type
β 1 problem (1 error, 0 warnings)
Nice ! That's what we wanted, it means that ESLint successfully detect errors.
Let's edit our source code to fix this error :
const myFunction = (): string => {
Stage it & commit :
$ git add .
$ git commit -m "My commit message"
Great, the commit has been made ! If you look at :
return 'This my function !'
You should notice that both quotation marks have been replaced by apostrophes thanks to Prettier.
Conclusion π
Well done ! You've successfully setup a linting mechanism on your workspaces thanks to Husky π
If you have any question about this article, feel free to ask it in the comments.
Have a nice day :)
Top comments (0)