Setup a project with Angular, ESLint, Prettier, Husky

Recently I was asked to initialize a new Angular project which is something I haven't done in a while. I took the opportunity to integrate and experiment with several tools that I believed could greatly benefit both my team and me. Here's the list of the tools installed :

  • Angular 17

  • ESLint

  • Prettier

  • Husky

  • pretty-quick/lint-staged

Initialize the Angular project

First, let's create our Angular project using the Angular CLI:

ng new my-project

You should be asked to specify some options, such as the stylesheet format you want to use. When the generation is completed, your project is ready to be used.

ESLint

ESLint is a powerful tool that allows you to improve your code quality standards and identify potential issues within JavaScript. Based on a set of rules, it statically analyzes your codebase and detects problematic patterns, potential bugs, or just stylistic inconsistencies. While you can find online dozens of rulesets, ESLint remains highly configurable. In this example, we will use the official Angular's schematics.

In your project's directory, run the following command:

ng add @angular-eslint/schematics

It will automatically install the required dependencies and adjust your configurations. You can make sure that everything is working properly by running:

ng lint

If you used a different ruleset or if you created your own, the command might raise some errors indicating Angular's template is not compliant with the rules defined.

You may have noticed that a .eslintrc.json file has been created during the installation. It's the configuration file for ESLint that will allow you to manage every rule used to lint your project: the rulesets used are specified in the extends section, and within the rules section you can either add new rules, disable some of the rulesets, or adjust their level. For instance, if you want to add a new rule forbidding the use of console.log and treating console.warn and console.error as warnings, you could add:

{
    ...
    "rules": {
        "no-console": ["error", { "allow": ["warn", "error"] }],
        ...
    }
}

You can find more information and examples in the official documentation.

Prettier

Let's now talk about code formatting. Every developer has asked himself one of these questions when joining a new team/project: "Should I use a single or double quote ?", "Should I insert a blank space here ?", "Do I need to break the line before the bracket, or after ?", "Tabs or spaces ?", etc...

While we could debate on which answer is the best for each of these questions, the most important thing we should all agree on is that the syntax should be consistent within the project. And Prettier is good for that. With Prettier, you define with your team a set of syntactic rules (or you can use an existing one) in a JSON format, and you let the tool adjust your files's syntax automatically when saving.

First, install the package with your favorite package manager (which should be pnpm btw):

pnpm add --save-dev --save-exact prettier

Then, if you want to create your own prettier configuration, you can go to the playground and adjust everything your way. Once done, you can copy the associated JSON and paste it into a .prettierrc.json at the root of your project's directory.

Then, to format every file according to your configuration, you can run this command:

pnpm exec prettier 'src/**' --write
# or 
npx prettier 'src/**' --write

Every file has now been formatted, except for those whose extension is not known (for instance the favicon.ico)

If you are using Visual Studio Code, you can configure your IDE to run prettier on a file every time it is saved. You can follow this tutorial.

Husky

These tools are great for making sure that your code base grows up in compliance with the rules defined in the different configuration files, but we still have to run manually each one to make sure everything is in order. Moreover, we could want to make sure every developer has checked if the code he wants to commit is compliant. To do so, we can use Husky. Husky allows you to define specific Git Hookswhich are basically scripts run on specific Git events. In our case, we want to lint and format files when a commit is created locally. But we also want to run Prettier and ESLint only on the files committed as we assume that this also has been done for every previous commit.

Let's install and initialize it:

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

A .husky directory with a pre-commit file should have been created. In this file, you can specify the instructions to be executed whenever a commit is trying to be created. It might be important to note that if one of the commands fails, the commit will not be created.

Now to make sure our tools are only run on the committed files, we will use lint-staged and pretty-quick:

pnpm install --save-dev lint-staged pretty-quick

In your package.json file, add a new section at the root level:

{
  "lint-staged":{
    "*.{ts,html,scss}": [
      "pretty-quick --staged",
      "eslint --fix"
    ]
  }
}

If you use another format for your stylesheets, please adjust the extension

Finally, add the following content to your .husky/pre-commit file:

pnpm exec lint-staged

Now everything should be working properly, every time you commit files, they will be formatted and linted. Note that the more files you commit at once, the longer it will take. It could be a good habit to try to reduce the size of your commits (see this article about atomic commits) and also to run ```ng lint``` manually from time to time when coding.

Conclusion

You can find the resulting project here.

0
Subscribe to my newsletter

Read articles from Christian Bonnaud directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Christian Bonnaud
Christian Bonnaud