A Complete Guide to Setting Up Dev Tools for Vanilla JavaScript Projects: Part 2

A Complete Guide to Setting Up Dev Tools for Vanilla JavaScript Projects: Part 2

Automating the process

📘Introduction

This blog is in continuation with its first part - A Complete Guide to Setting Up Dev Tools for Vanilla JavaScript Projects: Part 1.

So please check that one out before continuing with this one for better clarity.

Let’s do a quick review of the concepts we covered in part 1 of this blog.

We understood what lint tools are, why we need them, and how to set up ESLint, stylelint, commitlint and husky in a vanilla JS project. We also saw how to use them all individually via the command line and commitlint via git hooks using husky.

In my vanilla JS project, Shelf Share, I automated the use of these tools. It helped me speed up things and saved a lot of my time.

So, now we will proceed towards understanding the automation of these tools, setting them up in a way that they only run on the files present in the git staging area, followed by some general mistakes that you can avoid while setting up the whole process.

🤖 Automating lint tools with Husky

In part 1 of the blog, we learned about the commit-msg hook. I mentioned the pre-commit hook there but did not explain it so let’s start this blog from where we left off in part 1, the pre-commit hook.

We use the pre-commit hook to set up our linting process. This automates the process and we do not need to worry about running lint tools manually before each commit.

It is a very simple process, all we need to do is write the lint script in the pre-commit hook and that’s it. Git will always run this script whenever a commit is triggered.

Note that the pre-commit hook runs before the commit-msg hook and hence whenever the script inside the pre-commit hook encounters an error, it will stop the further execution, and the script of the commit-msg hook will not be executed, which is the commitlint script.

Therefore, if lint tools encounter any errors, Commitlint will not check the commit message until the linting errors are fixed, which I think is good as we deal with fewer errors at a time and can solve them one by one.

But if you still want the commit-msg hook to execute irrespective of any errors in the pre-commit hook, you can set up the lint script to always return true after the execution.

The below code is all you need in the pre-commit hook to set up the lint script that we created before.

npm run lint

Here is a snapshot of the output after setting up the pre-commit hook with lint errors in the source code.

Later on in this blog, we will set up the pre-commit hook to run the lint tools only on the staged files via the lint-staged tool instead of directly running the lint tools.

🔧 Prettier

Prettier is not a lint tool, but is a code formatter. While the lint tools focus on writing correct and bug-free code; and fixing problems in your code, prettier focus on the style of the code.

It focuses on the parts that may not create any problems in the code itself but affect how visually appealing and readable the code looks. It lets you write code in whatever way you want and makes it visually look good, automatically.

This tool is opinionated, meaning it has a huge set of predefined rules that it follows to make the code look good. It allows minimal customization, unlike lint tools, but is a great tool for creating consistency in code without needing to worry about it.

For example, if your code lacks proper indentation or in some places, there are single quotes and at some double, you can use prettier to resolve these issues. It will rewrite the whole code with proper indentation and you can choose to make all the quotes double or single to keep it consistent. Prettier supports various languages like CSS, JavaScript and its frameworks, HTML, JSON, etc.

Configuration

You can follow the official documentation to set up prettier in your code base. I would also recommend installing the prettier extension in your code editor as most of the editors do support the extension. This can help you format your code right when you save it.

After installation, you will have a configuration file in the root of your project named .prettierrc. Check the official documentation for updates in the naming pattern. You can leave this file empty if you just want to follow the default rules or you can make any customization here.

Below is an example of customizing this file.

{
    "singleQuote": true,
    "arrowParens": "avoid"
  }

You can add as many options as you want to ensure a consistent code style throughout the codebase.

Below is an example of code before and after running Prettier on it.

Before:

After:

You can see it adds semicolons, converts double quotes to single quotes, and puts the function calls one in a line.

Notice how it does not affect the error lines marked by ESLint. Prettier has nothing to do with these issues highlighted by ESLint, it simply makes the code visually better and makes it more readable and consistent.

Setting up Prettier with npm scripts

We can directly use prettier by globally installing it or via npx, but again, the best way is to write a npm script so later we can use it to automate the process.

Below is the script.

{
    "scripts": {
        "format": "prettier --write '*.{js, json, css, scss}'"
    }
}

This will run prettier on all the specified file formats. You can also use prettier --write to run it on all the files instead.

The --write option will automatically rewrite the code with the corrected formatting. If you do not want that and just want to see the changes that Prettier wants to make on your terminal, then you can remove this option. Then you will have to manually make the changes if you want them.

Now we can directly use this script via the command line manually or set it up to work with the pre-commit hook like we did with the lint tools. Instead of the lint script, we can put another script in the pre-commit hook that would run the lint script and the format script.

But instead of doing that, we will now change the scripts we made till now and use a tool called lint-stanged and run these tools only on the files that are present in the git staging area. This will make the process faster in large code bases.

🔧 Lint Staged

Running all the lint tools and code formatters on the whole code base can be slow when the code base is large.

It can also be problematic when you try to commit a few files that are completed but there are a few that still need to be committed and you are still working on them.

Running these tools on all the files via the pre-commit hook will not let you commit the completed files if there are any errors in the incomplete files even when you did not stage them.

This can create a mess and waste time. That’s why it is much better to run these tools only on the files that are ready to be committed. This way you can achieve the maximum efficiency the tools have to provide.

Configuration

You can follow the installation steps from the official documentation. You can choose to create a separate configuration file or just use the package.json file, where you set up the npm scripts, to set up the configuration for lint-staged.

I prefer to set up lint-staged in the package.json file itself, but if you want a separate file then you can follow the official documentation, the steps are very similar, just a few changes according to the file extension you choose.

Below is the lint-staged configuration for the tools we learned about till now.

{
  "lint-staged": {
    "*.js": [
      "eslint --fix",
      "prettier --write"
    ],
    "*.json": [
      "prettier --write"
    ],
    "*.{scss,css}": [
      "stylelint --fix",
      "prettier --write"
    ]
  }
}

With this setup, we do not need the format, lint, lint:css, and lint:js scripts that we created before. All of that work is handled by lint-staged itself while ensuring these commands run only on the staged files.

Note that the precedence here matters. You do not want to run prettier before the lint tools as prettier is a code formatter. The final formatted code should be from prettier and prettier should format the code that has been fixed by the lint tools. This way we can utilize all the tools and achieve the best final output.

Also note that whenever even one of the tools encounters an error, lint-staged will stop the further execution. This helps us easily debug our code by providing us with fewer errors at a time. It’s a feature, not a bug!

Here are the final scripts that are required for this whole process to work.

{
  "scripts": {
    "prepare": "husky install",
    "commitlint": "commitlint --edit",
    "lint-staged": "lint-staged"
  },
  "lint-staged": {
    "*.js": [
      "eslint --fix",
      "prettier --write"
    ],
    "*.json": [
      "prettier --write"
    ],
    "*.{scss,css}": [
      "stylelint --fix",
      "prettier --write"
    ]
  }
}

The prepare script is automatically created while installing Husky. It is used to properly set up git hooks with Husky.

The commitlint script is still required as we run it via the commit-msg hook instead of the pre-commit hook.

The lint-staged script will run lint-staged using the configuration we created. We will pass this script to the pre-commit hook to automate this process upon creating a commit.

You only need the code below in your pre-commit hook, and the whole process will get automated.

npm run lint-staged

Congratulations! You have successfully automated the application of these tools in your project. Now you never have to worry about the code style, analyzing the code for minor issues, or the format of your commits. All these issues will be reported to you by your tools.

🙅 Mistakes that I made and you can avoid

While using these tools for the first time, I made a lot of mistakes and got stuck in just the installation process for around 2 days. The mistakes were very small and silly but took a lot of my time. I have mentioned them here altogether so that you can avoid them.

Use the latest node version

To ensure compatibility of these tools, always make sure that Node is up to date. Using an older node version can lead to the failure of these tools and make you deal with errors that will consume a lot of your time.

In my case, my node version was a bit older and I got stuck with stylelint not working as intended. Always keep your node updated. You can use tools like nvm to manage your node versions.

Precedence matters

While setting up the lint-staged, I did not know that the precedence of the commands mattered. I wrote the prettier’s script before Stylelint and again got stuck. The rules I mentioned for Prettier were not getting applied as Stylelint was overwriting the code formatting done by Prettier.

We always want to run prettier in the end, after all the lint tools so we can keep the final code style as it is described in the prettier’s configuration file. And we always want prettier to run on the code that has been fixed by the lint tools. This way we can save a lot of time.

Refer to the official documentation

One of my major mistakes was to follow unofficial blog posts to set up the tools. The blogs were outdated and I ended up with a set-up that only threw errors and got a lot of code to debug just to find out that the whole set-up was not supported anymore.

That’s why, following the official installation documentation is the best way to install any tool in your project. You can learn about tools from other blogs if you want, but for the installation setup, always follow the official documentation. They always stay up-to-date and can save you a huge amount of time.

Global installations

Sometimes your scripts may not work and throw an error like prettier not found even after following the installation steps from official documentation.

It was a very strange error but a global installation fixed it for me. I was getting that error for prettier and once I installed it globally, it was working fine. So, if that ever happens to you with any of the tools, you can try globally installing them.

Use npm over npx

While referring to the official documentation, you may see that npx has been used for using the tools. This is generally good when you want to use the tools only once, but for a permanent and consistent usage, it is better to use npm.

npx directly fetches the packages from the online registry. This can create inconsistency as your project will not follow a particular version of the tools, but it will keep fetching the latest version.

This will reduce your control over the project and any new bugs or major changes can affect your whole code base without any warnings.

npm fetches the locally installed packages, hence it creates consistency over the usage of tools installed and prevents any introduction of new bugs from the latest releases.

This way you can use a consistent version throughout the project or the team. It is best to update the packages manually so you can have total control over your project.

Save your tools as devDependencies

When you follow the installation steps, sometimes your package gets saved as a dependency. You must know the difference between a normal dependency and a devDependency as it greatly affects how your code executes in development and production environments.

Dependencies

Packages saved in normal dependencies will be installed in the production environment as well. Meaning, this will affect the speed of your website on the client side.

You do not want to fill these with tools that only help a developer and have nothing to do with the client’s side. This is just a total waste of time and creates an unnecessary load. Only save those packages in a dependency that is required in a production environment.

DevDependencies

Packages saved in the devDependencies are those packages that a developer requires while developing the code. These are ignored in a production environment, meaning, these won’t be downloaded on the client’s side and will save up a lot of time and processing power.

This is where we save the lint tools and code formatting tools. These tools are only required while developing the project. After the development, they do not contribute further and hence there is no need for them in a production environment.

🏁 Conclusion

I hope I was able to help you understand how a few tools can save plenty of your time. These tools will enhance your codebase and help you follow global standards of writing code. You will encounter fewer errors and can have a smooth flow of work.

Overall, these tools are like a superpower that will enhance your coding and debugging skills and help you to write code like a pro!

A side note:

The tools mentioned in this blog are just a recommendation. Always conduct your research and explore beyond the recommendations.

The goal of this blog is not to just suggest a few tools but to help you understand the importance of such tools and why you need them, rather than providing a specific set of tools with installation instructions.

Always read the installation instructions from the official documentation as they are regularly updated, unlike blogs.

Happy coding!

🚀 Checkout the project

Here’s the project that I built with no frameworks, pure JS. Do check it out and let me know any feedback, I would love to hear your thoughts!

📚 Shelf Share: Search, Share, and Bookmark Books

Here is the GitHub repository for this project, if you are interested in the source code. Please do star it if you like it!

Shelf Share's Git Hub Repository

🔗 References