Skip to main content

Command Palette

Search for a command to run...

Improving Code Quality with Pre-Commits in JavaScript Projects (Husky)

Updated
5 min read
J

I am a dedicated software engineer specializing in front-end development and clean coding practices, bolstered by a comprehensive full-stack background. My professional journey blends technical expertise with effective team leadership, focusing on fostering an environment of continuous learning and accountability. Driven by a passion for technology and people, I aim to innovate and inspire in every project I undertake.

"Code quality is critical to project success, but catching issues early can be a challenge. Pre-commit hooks provide a powerful way to shift quality checks left, saving time and reducing costly fixes. This blog will guide you through setting up pre-commit hooks for your JavaScript and TypeScript projects."

TTL;DR: Quick Setup Guide

Use this commands if you don’t like to read the details, otherwise go to next step

# BASIC CONFIG 
git init # Start git config 
npm init # Start npm config 
mkdir src # Create a src folder 
touch ./src/index.js # Create a file 
echo -e "node_modules\n.pnpm-store" > .gitignore # Create a .gitignore file to exclude unnecessary files like node_modules and .pnpm-store from version control.

# HUSKY
pnpm add --save-dev husky
pnpm exec husky init
echo "pnpm pre-commit" > .husky/pre-commit

# LINT STAGED
pnpm add --save-dev lint-staged # requires further setup
echo "{ \"./src/**/*\" :[\"eslint --fix\"], \"*.{json,js,ts,jsx,tsx,html}\": [\"prettier --write --ignore-unknown\"]}" > .lintstagedrc

# ESLINT
pnpm create @eslint/config@latest # Answer the questions according to you current project needs.
pnpm eslint ./src/* # run eslint to detect errors 

# PRETIER
pnpm add --save-dev --save-exact prettier eslint-config-prettier # Install prettier 
echo "{}" > .prettierrc # Create config file for prettier
echo "build\ncoverage\n" >> .gitignore # Add ignored folers
pnpm exec prettier . --write # Format your JS file 

# COMMIT LINT 
pnpm add --save-dev @commitlint/{cli,config-conventional} # Install commit lint 
echo "export default { extends: ['@commitlint/config-conventional'] };" > commitlint.config.mjs # Create commit lint config file
echo "pnpm dlx commitlint --edit \$1" > .husky/commit-msg # Add commit message linting to commit-msg hook

add this to the package.json

{
  "main": "./src/index.js",
  "type": "module",
  "scripts": {
    "pre-commit": "lint-staged",
    "prepare": "husky",
  }
}

eslint.config.js

import globals from "globals";
import pluginJs from "@eslint/js";
import eslintConfigPrettier from "eslint-config-prettier";

/** @type {import('eslint').Linter.Config[]} */
export default [
  { languageOptions: { globals: globals.browser } },
  pluginJs.configs.recommended,
  eslintConfigPrettier,
];

Initial project config

Set up a basic JavaScript project:

git init # Start git config 
npm init # Start npm config 
mkdir src # Create a src folder 
touch ./src/index.js # Create a file 
echo -e "node_modules\n.pnpm-store" > .gitignore

Update ./src/index.js with the following content:

//This function has an intentional bad structure and error for exercise purposes.
   export function sayHello(number
   ) 
        {
    if(number % 2 = 0){
        return true;
    }
 return false;
                    }

Make your first commit

git add . 
git commit -m "new code change" # this commit dont follow any standar for exercise purpose
git log --oneline # log you current commits

Note that this commit contains errors, which is why tools like Husky and ESLint are essential to prevent such issues from progressing further.

🧰 Basic tools configuration

Key Tools to Use

  1. Husky: Automates Git hooks for running pre-commit checks.

  2. Lint-Staged: Ensures only staged files are linted for efficiency.

  3. ESLint: Catches code quality issues and enforces coding standards.

  4. Prettier: Formats code for consistent indentation and readability.

  5. Commit-Lint: Validates commit messages for clarity and consistency.

For this blog we will use pnpm, so install it pnpm.

1 . Install Husky ( link )

Install and initialize Husky:

pnpm add --save-dev husky
pnpm exec husky init

This creates a .husky folder with a pre-commit file. Update it to run lint checks:

|_.husky
|__ pre-commit

change the ./.hunsky/pre-commit file to execute the lint job

echo "pnpm pre-commit" > .husky/pre-commit

Now, add another commit with the following errors for testing:

 // Intentional bad structure for testing
export function sayHello(number
   ) 
        {
            const result = false;
    if(number % 2 == 0){
        result = true;
    }
 return result;
                    }

Update package.json to include pre-commit linting:

{
  "name": "precommit-ts",
  "main": "./src/index.js",
  "type": "module",
  "scripts": {
    "pre-commit": "lint-staged",
    "prepare": "husky",
  },
  "devDependencies": {
    "@eslint/js": "^9.18.0",
    "eslint": "^8.57.1",
    "globals": "^15.14.0",
    "husky": "^9.1.7"
  }
}

2 . Install Lint-staged

Configure lint-staged to lint only staged files:

pnpm add --save-dev lint-staged # requires further setup
echo "{ \"./src/**/*\" :[\"eslint --fix\"], \"*.{json,js,ts,jsx,tsx,html}\": [\"prettier --write --ignore-unknown\"]}" > .lintstagedrc

3 . Install Eslint ( link )

pnpm create @eslint/config@latest # Answer the questions according to you current project needs.
pnpm eslint ./src/* # run eslint to detect errors

4 . Install Prettier & eslint+prettier

This allow you to ident your code

pnpm add --save-dev --save-exact prettier eslint-config-prettier # Install prettier 
echo "{}" > .prettierrc # Create config file for prettier
echo "build\ncoverage\n" >> .gitignore # Add ignored folers
pnpm exec prettier . --write # Format your JS file

Add eslint-config-prettier to your ESLint configuration – either to eslintrc or to eslint.config.js (flat config).

import globals from "globals";
import pluginJs from "@eslint/js";
import eslintConfigPrettier from "eslint-config-prettier";

/** @type {import('eslint').Linter.Config[]} */
export default [
  { languageOptions: { globals: globals.browser } },
  pluginJs.configs.recommended,
  eslintConfigPrettier,
];

5 . Commit lint.

follow official docs for updated instructions

pnpm add --save-dev @commitlint/{cli,config-conventional} # Install commit lint 
# Create commit lint config file
echo "export default { extends: ['@commitlint/config-conventional'] };" > commitlint.config.mjs
echo "pnpm dlx commitlint --edit \$1" > .husky/commit-msg # Add commit message linting to commit-msg hook

Conventional Commits enforce a clear, standardized commit message format that organizes Git history, improves traceability, and simplifies collaboration. By categorizing changes (e.g., feat, fix), it enables automated versioning, streamlined release note generation, and easier error identification. This ensures consistency, accelerates code reviews, and supports tools like Semantic Versioning. Learn more at Conventional Commits.

Conclusion

By implementing pre-commit hooks and using tools like Husky, ESLint, Prettier, and Commit-Lint, you ensure cleaner commits, reduce errors, and foster better collaboration.

These steps will help you shift left and maintain high code quality from the start.

58 views
Z
zgd1y ago

We are willing to pay a high price to acquire the source code of a mobile game that is compatible with both Android and iOS platforms, for the purpose of learning and research. The game must meet the following criteria: it should be developed by a top-tier gaming company within the past 5 years, fully completed and matured, and preferably of the multiplayer online MMORPG or ARPG genre. If your game meets our interest, we will proceed with the transaction promptly and offer an upfront payment as a gesture of goodwill. Contact me q791864008q@gmail.com

How to ?

Part 1 of 1

More from this blog

L

Lets talk about software

2 posts

Exploring software development through my lens. Dive into JavaScript, front-end, architecture, algorithms, and more. Join me on this journey of learning and sharing insights in tech.