Maintaining clean, consistent code across a development team can be challenging. Despite coding guidelines, code quality can vary, especially in collaborative environments. Automated code linting and formatting help ensure that all code adheres to established quality and style standards, making the code easier to read, maintain, and scale. However, running these tools manually can be cumbersome and error-prone.
This is where Git Hooks, Husky, and Lint-Staged come in. Together, these tools allow you to automate linting and formatting every time a commit is made, ensuring only clean, high-quality code reaches the main repository. In this article, we’ll explore how to set up Husky and Lint-Staged to harness the power of Git Hooks and automate code quality checks at the commit stage.
👉 Download eBook - JavaScript: from ES2015 to ES2023
Understanding Git Hooks: The Basics
Git Hooks are scripts that trigger actions at various stages of a Git workflow. These scripts can be used to enforce standards by executing commands during specific Git events, like pre-commit
(before a commit is finalized) or pre-push
(before code is pushed to a remote repository). Pre-commit hooks are especially useful for enforcing code quality checks, as they run before code is committed, allowing developers to catch and fix issues early in the process.
Some common use cases for Git Hooks include:
- Running tests to prevent broken code from being committed.
- Enforcing proper commit message conventions.
- Running linters to ensure code consistency and adherence to standards.
Introduction to Husky and How It Simplifies Git Hooks
While Git Hooks can be configured manually, this setup can be complex and may not integrate well across different environments. Husky simplifies this process by allowing developers to manage Git Hooks easily within a project. It abstracts away the manual configuration, offering a reliable and scalable way to add Git Hooks to projects.
Husky works by letting you define Git Hooks in your project’s package.json
file, which makes setup and maintenance easier for all contributors. Here’s a quick look at how to add Husky to a project.
What is Lint-Staged and How It Complements Husky?
Lint-Staged is a tool that optimizes code linting and formatting by running these tasks only on staged files, rather than the entire codebase. This improves efficiency, especially in larger projects where linting the entire codebase would take too much time during each commit.
Using Lint-Staged with Husky enables a seamless workflow:
- Lint-Staged processes only the files that are currently staged for a commit.
- If any issues are found, the commit is halted until they’re resolved.
- This combination prevents low-quality code from entering the codebase while keeping the process fast.
With this setup, Husky manages the hook itself, while Lint-Staged determines which files need linting or formatting, optimizing the workflow for performance.
Setting Up Husky and Lint-Staged to Automate Linting and Formatting
Here’s a step-by-step guide to implementing Husky and Lint-Staged in a JavaScript or Node.js project.
Step 1: Install Husky
Start by installing Husky as a development dependency:
npm install husky --save-dev
Next, initialize Husky in the project:
npx husky install
This command creates a .husky
directory where Git Hooks are stored. You can now set up specific Git Hooks, such as a pre-commit hook.
Step 2: Set Up the Pre-Commit Hook
To set up a pre-commit hook, use the following command:
npx husky add .husky/pre-commit "npm test"
This command adds a pre-commit hook that will run npm test
before each commit. You can replace npm test
with other commands, like linting or formatting.
Step 3: Install Lint-Staged
Install Lint-Staged as a development dependency:
npm install lint-staged --save-dev
Step 4: Configure Lint-Staged in package.json
In your package.json
, add a lint-staged
configuration. Here’s an example setup to run ESLint and Prettier:
{
"lint-staged": {
"*.js": ["eslint --fix", "prettier --write"]
}
}
This configuration applies ESLint and Prettier to any staged .js
files, automatically fixing any linting or formatting issues before they are committed.
Step 5: Link Lint-Staged with Husky
Finally, update the Husky pre-commit hook to use Lint-Staged:
npx husky add .husky/pre-commit "npx lint-staged"
Now, every time you stage and commit code, Husky triggers Lint-Staged to lint and format only the staged files, ensuring that only clean, consistent code is committed.
Example Workflow: A Pre-commit Check for Code Quality
Let’s walk through an example workflow that enforces code quality during the commit process:
-
Stage Files: You add changes to the staging area with
git add
. -
Attempt Commit: You run
git commit
, which triggers the Husky pre-commit hook. - Lint-Staged in Action: Lint-Staged runs, identifying only the staged files for linting or formatting tasks.
- Fix and Commit: If there are any linting or formatting issues, the commit fails. You then review and fix the issues before reattempting the commit.
This workflow ensures code consistency at the commit stage without any manual intervention.
Troubleshooting Common Issues
Issue 1: Permission Errors with Git Hooks
On some systems, Husky’s Git Hooks may encounter permission errors. Run the following command to ensure the .husky
directory has the correct permissions:
chmod ug+x .husky/*
Issue 2: Lint-Staged Not Running as Expected
If Lint-Staged isn’t running correctly, check your package.json
configuration for syntax errors. Ensure you’re specifying the correct file extensions for linting (e.g., *.js
).
Issue 3: Husky Hooks Not Triggering
Make sure that Husky is installed and initialized. Running npx husky install
can help resolve setup issues if the hooks aren’t triggering correctly.
Benefits and Best Practices
Key Benefits
- Consistent Code Quality: Ensures all committed code meets linting and formatting standards.
- Improved Team Productivity: Reduces manual checks and code review time spent on formatting.
- Streamlined Workflow: Automates code checks, reducing the chances of low-quality code in the codebase.
Best Practices
- Run Tests on pre-push: While linting on pre-commit is effective, running tests on pre-push can further enforce code quality.
- Avoid Overly Strict Rules: Ensure that linting and formatting rules are agreed upon to avoid developer friction.
-
Use a .lintstagedrc File: For more complex configurations, consider a separate
.lintstagedrc
file for Lint-Staged setup.
Conclusion: Streamlining Code Quality with Automation
Automating code quality checks with Git Hooks, Husky, and Lint-Staged helps streamline development workflows by catching issues early in the commit process. This setup ensures that only well-linted and properly formatted code makes it to the codebase, saving time and improving overall code quality. By integrating these tools, you empower your development team to focus on building features rather than worrying about formatting and style.