November 23, 20225 min read

Keep Your Code Consistent using Husky, ESLint, Prettier, and Lint-staged

Setup javascript/typescript project for better quality code and developer experience.

When I was in the early phase of learning software development, a working code is what all mattered. As my experience progressed, I learned the importance to write standardized, and no 💩 code. Most of the time it's normal that some 💩 code is being pushed into a repository. We're just human beings. We made mistakes.

Sometimes, it wasn't a big deal to have 💩 code in a repository, but a few times I found myself needing hours to find a bug after such a commit. It'll be messier when we are working with a team. We need a tool to prevent us from committing a code that contained errors and saving time for us. That’s one reason why we need linter.

Lint, or a linter, is a static code analysis tool used to flag programming errors, bugs, stylistic errors, and suspicious constructs. The term originates from a Unix utility that examined C language source code. --- Wikipedia

The idea is to leverage Git hooks (pre-commit) to check our code before the code is pushed to a repository.

In this article, we'll automate the linting process using linter (ESLint), code formatter (Prettier), Git Hooks (Husky), and Lint-stagged to make sure the code is formatted and fixed before being pushed to a repository.

Required packages installation

We'll install the listed packages below:

  • ESLint - ESLint is a tool for identifying and reporting on patterns found in ECMAScript/JavaScript code, to make code more consistent and avoid bugs
  • Prettier - is a code formatter based on configuration (.prettierrc)
  • Lint-staged - is a tool to lint staged git files
  • Husky - is a tool to work with git workflow (Git hooks). See this for more detail regarding git hooks.

Run this command to install the required packages :

yarn add -D eslint prettier lint-staged husky

if your are using npm, run this command:

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

ESLint Configuration

Let's start setup some configurations for the packages. I'll start with ESLint first. To begin ESLint you can run this command:

yarn eslint --init

or

npx eslint --init

You'll be prompted with some questions, answer according to your project specification.

eslint config

The configuration file would look something like the below:

eslintrc.json
{
  "env": {
    "browser": true,
    "es2021": true
  },
  "extends": ["plugin:react/recommended", "airbnb"],
  "overrides": [],
  "parserOptions": {
    "ecmaVersion": "latest",
    "sourceType": "module"
  },
  "plugins": ["react"],
  "rules": {}
}
json

There is an alternative to the previous command. Just create eslintrc.json and paste the above configuration into it.

To override the code style enforcement you need to insert your style in the rules section. Read more about ESLint rules by reading the documentation.

Here is an example of eslintrc.json

eslintrc.json
{
  "env": {
    "browser": true,
    "es2021": true
  },
  "extends": ["plugin:react/recommended", "airbnb"],
  "overrides": [],
  "parserOptions": {
    "ecmaVersion": "latest",
    "sourceType": "module"
  },
  "plugins": ["react"],
  "rules": {
    "no-unused-vars": "warn",
    "no-console": "error",
    "indent": ["warn", "tab"],
    "quotes": ["error", "single"],
    "semi": ["error", "always"]
  }
}

The eslintignore File

You can tell ESLint to ignore specific files and directories by creating a .eslintignore file in your project’s root directory.

for example, the following omit linting on node_modules, dist, and .next directory.

.eslintignore
node_modules
dist
.next

Prettier Configuration

Create an empty file named .prettierrc.json.

There are various rules for the prettier configuration files. Take a look at Prettier Documentation.

Here is an example of the configuration.

.prettierrc
{
  "trailingComma": "es5",
  "tabWidth": 4,
  "semi": false,
  "singleQuote": true
}

You can ignore some files to be formatted by prettier by creating an empty file named .prettierignore.

Here is an example of prettier ignore configuration:

.prettierignore
# Ignore artifacts:
build
coverage
.next

# Ignore all HTML files:
*.html

Lint-Staged Configuration

There are several ways to configure lint-staged in your project:

  • lint-staged object in package.json
  • .lintstagedrc file in JSON/YAML format
  • .lint-staged.config.js

Here is an example lint-staged configuration using an object in package.json

package.json
{
...
"lint-staged":{
    "src/**/*.{js,jsx,ts,tsx}": "eslint --cache --fix",
    "src/**/*.{js,jsx,ts,tsx,css,scss,md}": "prettier --write --ignore-unknown"
  }
}

By default, lint-staged will run configured tasks concurrently. This means that for every glob, all the commands will be started at the same time. With the above config, both eslint and prettier will run at the same time.

Configure Husky

In this section, we'll configure git hooks using Husky.

  1. Enable hooks
yarn husky install

or

npx husky install
  1. Optional, add prepare script in package.json to automatically enable husky after install
package.json
{
...
"scripts":{
... //other scripts
"prepare": "husky install"
}
}
  1. Add lint-staged command in pre-commit hooks
yarn husky add .husky/pre-commit "yarn lint-staged"

It'll generate file in .husky/pre-commit with below content:

.huskty/pre-commit
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
 
yarn lint-staged
 

Now, we've finished all the configuration needed. Now try to commit our code changes.

git add .
git commit -m "first init"

If there is a linting error in your code, your commit will be automatically aborted. Fix the code informed by ESLint and try again until you're successfully committed a clean code to your repository.

Further resources

Here are some references to improve the understanding regarding DX (Developer Experience)