DEV Community

Cover image for Set up a git precommit hook with husky, lint-staged, prettier, and stylelint
Nick Taylor
Nick Taylor

Posted on • Updated on • Originally published at iamdeveloper.com

Set up a git precommit hook with husky, lint-staged, prettier, and stylelint

There's a few things I always set up when working on a frontend project: ESLint, Prettier, husky and lint-staged.

ESLint

ESLint for linting frontend files: JavaScript, JSX and TypeScript (if the project uses TypeScript). There are all kinds of rules and plugins for this, but the gist of using a linter is to keep your code adhering to a project's standards/styles.

A screen shot of a lint error

Prettier

Prettier is for formatting your code. It is opinionated and offers some configuration but it is minimal, for example single quotes vs. double quotes.

prettier code formatting tool in action formatting some code

stylelint

stylelint as the package name implies, is a linter for Cascading Style Sheets (CSS).

Side Effect: Improving Code Reviews

ESLint, stylelint and Prettier enable you to remove any discussion of what they do from a code review, because the rules are already set in place. This is great because it allows you to focus on the actual code review which is the bug you're trying to fix or a feature you're implementing.

husky

Note: As of Husky version 7, the setup is completely different. Please follow the steps in the 4 to 7 migration guide.

husky is a node package that makes creating Git hooks a joy. What's a Git hook? It's a script that runs during an event in a repository. For example, before a commit. Once the husky package is installed, all that is required is a configuration to decide which Git hooks to use and what to run for that particular hook.

Here is a sample configuration.

"husky": {
  "hooks": {
    "pre-commit": "echo 'hi'"
  }
}
Enter fullscreen mode Exit fullscreen mode

When a file is being committed to the repository, the above configuration will run echo 'hi' before the file is committed.

A Git pre-commit hook running in a terminal before a commit

lint-staged

lint-staged is a node package that makes it easier to run tasks for staged files in a Git repository. If we go back to our example above that echo's hi, we can change that command to lint-staged.

"husky": {
  "hooks": {
    "pre-commit": "lint-staged"
  }
}
Enter fullscreen mode Exit fullscreen mode

If we commit a file, the Git pre-commit hook will run lint-staged, but nothing will happen. We need to let lint-staged know what we want to do during the pre-commit. Let's get a configuration set up for lint-staged.

"lint-staged": {
  "*.{js}": [
    "prettier --write"
  ]
}
Enter fullscreen mode Exit fullscreen mode

Now if we commit a file, the pre-commit hook will run and if any JavaScript files are being committed, the pre-commit hook, thanks to lint-staged will run prettier on the file and update the file with any formatting changes and then commit the file.

A Git pre-commit hook running lint-staged tasks

Putting it All Together

All these tools together make for a great automated workflow in regards to coding standards/style guidelines for a project.

Now let's bring it all together so you can use this in your own project.

You'll need to install all the dependencies mentioned above plus a few more. I'll explain why in a minute.

npm install -D eslint prettier eslint-config-prettier eslint-plugin-prettier husky lint-staged stylelint stylelint-config-standard
Enter fullscreen mode Exit fullscreen mode

eslint-config-prettier and eslint-plugin-prettier stylelint stylelint-config-standard are required so that eslint is only in charge of rules that do not related to formatting as prettier handles formatting.

If you're wondering what the -D is for, that's so they get installed as devDependencies instead of dependencies in the package.json. For more on that, see Specifying dependencies and devDependencies in a package.json file.

In the root of your project, create a file called .eslintrc.js. This will house the eslint configuration that we want. We'll go with the eslint recommended rules.

/* eslint-env node */
module.exports = {
  extends: ['eslint:recommended', 'prettier'],
  plugins: ['prettier'],
  parserOptions: {
    ecmaVersion: 2018, // Put whatever version you want here
  },
  env: {
    browser: true,
  }, 
};
Enter fullscreen mode Exit fullscreen mode

Note: /* eslint-env node */ is being used as it's a frontend project and the .eslintrc.js file is Node.js. It allows us to say, "This file is a Node.js file". Thanks to Rafi for pointing this out to me.

This is a base eslint configuration. If you were for example using React in your project, there would be additional configuration for React eslint rules.

In the root of your project, create a file called .stylelintrc.json. This will house the stylelint configuration that we want. We'll go with the stylelint recommended rules.

{
  "extends": "stylelint-config-standard"
}
Enter fullscreen mode Exit fullscreen mode

This is a base stylelint configuration. Feel free to expand on these standard stylelint rules.

Next up we need to our husky and lint-staged configurations. In your package.json file add these two configuration sections.

"lint-staged": {
    "*.js": [
        "eslint —-fix",
        "prettier --write"
    ],

    "*.{css,scss}": [
        "stylelint"
    ]
},
"prettier": {
    "singleQuote": true,
    "trailingComma": "all",
    "printWidth": 80,
    "tabWidth": 4
}
Enter fullscreen mode Exit fullscreen mode

If you don’t trust the robots for fixing your code, remove the —-fix argument off of the eslint command.

The prettier configuration above is what I use, but feel free to tweak it to your liking.

All the moving parts are running now. If you end up using a boilerplate these tools might already be included. For example the Create React App toolchain comes with eslint.

Bonus: Run jest Tests

I added this as a bonus tip, because not all projects use jest.

But... if your project uses jest, you can also run tests related to files that are being committed.

"lint-staged": {
    "*.js": [
        "eslint —-fix",
        "prettier --write",
        "jest --findRelatedTests"
    ]
}
Enter fullscreen mode Exit fullscreen mode

Learn More About Your Tools

I strongly encourage you to dig further into all the tools discussed. Knowing your tools really well is a super power.

ESLint, prettier, stylelint, husky and lint-staged are great tools for the frontend, now go make something great with this setup!

Until next time folks!

Character in a film saying "Yes! That is awesome

Oldest comments (5)

Collapse
 
rafi993 profile image
Rafi

It would be awesome if this whole thing could be setup on any repo by running

npx frontend
Enter fullscreen mode Exit fullscreen mode
Collapse
 
nickytonline profile image
Nick Taylor

It could, I just haven’t done it. 😎

Collapse
 
rafi993 profile image
Rafi

I have created a package inspired by this npmjs.com/package/frontend-dev user can use it by running

npx frontend-dev
Enter fullscreen mode Exit fullscreen mode

here is the source to the repo github.com/Rafi993/frontend-dev

Collapse
 
eclecticcoding profile image
Chuck

Great good Nick. This can be more streamlined by created personal user environments or Boilerplates, which ironically I have written about :-)

Thread Thread
 
nickytonline profile image
Nick Taylor

Thanks Chuck!

Yeah, I can’t remember when boilerplates came out, but it’s a great feature on GitHub. We use it on react-slingshot.

GitHub logo coryhouse / react-slingshot

React + Redux starter kit / boilerplate with Babel, hot reloading, testing, linting and a working example app built in


Build status: Linux Build status: Windows Dependency Status Coverage Status

A comprehensive starter kit for rapid application development using React.

Why Slingshot?

  1. One command to get started - Type npm start to start development in your default browser.
  2. Rapid feedback - Each time you hit save, changes hot reload and linting and automated tests run.
  3. One command line to check - All feedback is displayed on a single command line.
  4. No more JavaScript fatigue - Slingshot uses the most popular and powerful libraries for working with React.
  5. Working example app - The included example app shows how this all works together.
  6. Automated production build - Type npm run build to do all this:

React Slingshot Production Build

Get Started

  1. Initial Machine Setup

    First time running the starter kit? Then complete the Initial Machine Setup.

  2. Click "Use this template"

    Click the green "Use this template" button at the top of this page and enter a name and description for your repo.

  3. Run the setup

I was contemplating making a template, but opted to go with explaining the moving parts instead. I could see it being more of a cli longer term which could detect the type of project, check if certain things were in place already, add lint specific rules based on project type etc.