Stop Silly Code Errors with Pre-commit Hooks, ESLint, and Prettier

Development tutorial - IT technology blog
Development tutorial - IT technology blog

A Costly Lesson from a 2 AM Typo

My phone vibrated incessantly with Sentry notifications. The system was reporting a massive wave of 500 errors right after a hotfix was merged. After 45 minutes of digging through logs, I found the culprit: an extra curly brace and an undefined variable caused by a rushed copy-paste. The developer in charge forgot to run the linter locally. Worse, CI/CD was skipped to “deploy faster.”

If you’ve ever spent a whole morning just adjusting commas or indentation to match the team’s style, you’ll understand why I’m obsessed with automation. In my latest project with five developers, I implemented this automated control process. The results were surprising: we reduced useless arguments about code formatting in Pull Requests by 80%. Everything is handled cleanly by automation before the code even leaves the local machine.

The Triple Threat That Lets You Sleep Soundly

To keep code clean, we need a multi-layered control system. Instead of waiting until it’s pushed to the server to check, I block errors right at the “gateway” of the local machine.

  • ESLint: This tool acts like a professional proofreader. It points out logical errors like undeclared variables or code snippets with potential security risks.
  • Prettier: This is the beautifier. Prettier doesn’t care if the code is right or wrong; it just ensures every file is aligned and follows the formatting standards agreed upon by the team.
  • Husky & Lint-staged: These two tools act as “checkpoints.” When you type git commit, Husky triggers lint-staged to force ESLint and Prettier to check only the modified files. If there are still errors, the commit command is rejected immediately.

Setup Guide from Scratch

Assuming you are working on a Node.js or React project. It only takes about 10 minutes to get this framework running smoothly.

Installing ESLint and Prettier

First, install the necessary packages. I use eslint-config-prettier to ensure these two tools don’t have conflicting rules.

npm install -D eslint prettier eslint-config-prettier eslint-plugin-prettier

Next, create the .eslintrc.json configuration file. Here is a standard configuration I often use for real-world projects:

{
  "env": {
    "browser": true,
    "es2021": true,
    "node": true
  },
  "extends": [
    "eslint:recommended",
    "plugin:prettier/recommended"
  ],
  "rules": {
    "no-console": "warn",
    "no-unused-vars": "error"
  }
}

Don’t forget the .prettierrc file to define the general style. My team usually prefers single quotes and avoids excessive semicolons:

{
  "semi": true,
  "tabWidth": 2,
  "singleQuote": true,
  "trailingComma": "es5"
}

Activating Husky – Automating Control

Installing tools without enforcing their use makes them easy to forget. Husky helps you automate this via Git Hooks.

npx husky init && npm install

This command creates the .husky directory. However, scanning the entire project every time you commit will be very slow if the project has thousands of files. To optimize, we need lint-staged.

Optimizing Performance with Lint-staged

Install lint-staged to only check files currently in the staging area (staged files):

npm install -D lint-staged

Add the following configuration to package.json:

{
  "lint-staged": {
    "*.{js,jsx,ts,tsx}": [
      "eslint --fix",
      "prettier --write"
    ]
  }
}

Finally, update the .husky/pre-commit file to call lint-staged. From now on, every time you commit, the machine will do the work for you.

Real-world Experience: When the Machine Speaks Up

Try creating an app.js file with an extra variable and messy formatting. When you type git commit -m "feat: update", the terminal will show the scanning process. If ESLint finds a no-unused-vars error, it will block the commit. You are forced to clean up the code to proceed. Conversely, if it’s just a line break error, Prettier will automatically “fix” the code before allowing the commit to succeed.

Hard-learned Lesson: Don’t Be Too Strict Initially

I once made the mistake of applying too many strict rules on day one. Team members were constantly blocked, leading to frustration and them finding ways to use --no-verify to bypass the checks. My advice: Start with the most basic rules to avoid runtime errors. Then, discuss with the team and gradually add style rules over time.

Conclusion

Setting up Pre-commit Hooks takes no more than 15 minutes, but the value it brings is immense. It saves your team hours of code review and avoids sleepless nights over silly production errors. Build an engineering culture where code quality is guaranteed automatically and professionally.

Share: