Experimenting with linters, formatters, and pre-commit hooks
Tags: opensource, javascript, beginners, testing
Published: 2022-11-14 19:58:15

We all have different integrations in our favourite IDE that helps us format and catch problems in the code we write. However, when collaborating on projects with developers around the globe, we need to specify rules in our project so we can get everyone's code formatted and patched using [Static Analysis](https://www.perforce.com/blog/sca/what-static-analysis) tools such as [Prettier](https://prettier.io/docs/en/index.html) and [ESLint](https://eslint.org/docs/latest/) in the same way.

I equipped [Siteit](https://github.com/SerpentBytes/siteit) - an SSG tool that I am one of the maintainers of, with static analysis tooling to ensure we, as developers, are writing code that is _lint-free_, and also correctly formatted. 

## Table of Contents
1. [Prettier](#prettier)
2. [EsLint](#eslint)
3. [husky](#husky)
 - pretty-quick
 - lint-stagged


### Prettier
[Prettier](https://prettier.io/docs/en/index.html#footnotes) is a source code formatter supporting various programming languages and frameworks. Prettier ensure formatting throughout the entire codebase is consistent.

#### Reasons I chose Prettier
- Integrates well with VS Code
- Write code, let Prettier handle formatting
- Consistent formatting throughout the codebase for all contributors

#### Setting up Prettier
First I [installed](https://prettier.io/docs/en/install.html) Prettier locally by running:
```node
npm install --save-dev --save-exact prettier
``` 
Then I created an empty config file to let VS Code know I am using Prettier by running:

```node
echo {}> .prettierrc
```

I configured my Prettier `config` file with the following [`options`](https://prettier.io/docs/en/options.html):

```node
{
  "trailingComma": "es5",
  "tabWidth": 2,
  "semi": true,
  "singleQuote": true,
  "bracketSpacing": true,
  "arrowParens": "always"
}
```

Lastly, I created a `.prettierignore` file to let Prettier know which files to ignore.

In my case, I wanted to ignore the following:
```
# Ignore artifacts:
build
node_modules
.*
dist
```
#### Running Checks
With Prettier configured correctly, I can check for formatting issues in a specific file by running the following from the terminal:
```node
npx prettier --check <file_name>
```

#### Formatting Code
Similar to running checks, to format a specific file using Prettier, I can run the following from the terminal:
```node
npx prettier --write <file_name>
```

### ESLint
[ESLint](https://eslint.org/docs/latest/user-guide/getting-started) analyses the JavaScript code to detect problematic patterns. It aims to make source code consistent and assist in avoiding bugs.

#### Reasons I chose ESLint
- One of the most popular _linters_ 
- Good at detecting bugs in Javascript code
- Easily configurable

#### Setting up ESLint
[Installing](https://eslint.org/docs/latest/user-guide/getting-started) ESLint was pretty straightforward. 
I had to run the following command and follow the CLI prompts.

```node
npm init @eslint/config
```
Next, just like with Prettier, I had to [configure](https://eslint.org/docs/latest/rules/) the ESLint with [rules](https://eslint.org/docs/latest/rules/) best suited for Siteit. 

Lastly, I had to create a `.eslintignore` file, to let ESLint know which files to ignore when looking for bugs in the codebase. 

#### Running Checks
With ESLint configured correctly, I can execute the following from the terminal to check for _lint_ in my code:

```node
npx eslint <file_name>
```
#### Fixing Bugs 
Similarly, to running checks, I can _fix_ the errors detected by ESLint by running the following:

```node
npx eslint --fix <file_name>
```

### Husky
[Husky](https://typicode.github.io/husky/#/) is a pre-commit hook that executes custom scripts against your repository. Husky can run tests, lint code, and do much more.

I have configured a pre-commit hook using Husky for Siteit to ensure that `staged` files are correctly formatted and are _lint-free_. 
The tools I am using are `pretty-quick` and `staged-lint`. These tools check for formatting errors using Prettier and linting bugs using ESLint configuration, _only_ on files the user tries to commit. 
If errors are found, they are _fixed_, and the `git commit` command is successfully executed. If there are errors, the tools will try to fix them and commit the changes. Suppose the errors cannot be corrected automatically; in that case, the `git commit` command fails, as the developer must manually address the problems in the code detected by the static analysis tools. 

#### Result
When I try to `commit` a file that contains errors that cannot be fixed automatically, `commit` is ignored:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e6fj7zvtg7vo2e22pyb3.png)

### Testing the Codebase
I have updated `scripts` in `package.json` to automate checking and fixing formatting and _linting_ errors. 

Before staging changes, the developers can run the following `scripts` to _check_ their code for errors
```node
npm run prettier:check
npm run lint
``` 

Similarly, to _fix_ the bugs in the codebase, developers can run the following `scripts`:

```node
npm run prettier:format
npm run lint:fix
```

## Learning Outcomes
When checking for _linting_ errors, I found a lot of instances where I should be using `const` instead of `let`, as the `variable` values are never modified. 

Overall, it improved my codebase by correcting bugs that are _easy_ to miss. 

These tools are really a life saver.