post-image

Standardize Your Next.js Project with ESLint and Husky

January 30, 2022

Tutorial

Share on Twitter

Table of contents

Disclaimer

In this article, I’ll focus on Next.js (using Typescript) based project. You can adapt it to your own needs based on your project source code and the problem that you’ve faced.

Introduction

Based on my experience in the software development world, Javascript (and Typescript) is the “wildest” programming language. We can use any code styles or conventions by our own preference in every project if we use Javascript.

When I work on a personal project, actually it’s not a big problem because I code for myself and only me who know the code, LOL. But imagine this, how if I have to work in a team with several people and each of them has their own code style? BOOOM, it will be chaos right?

This is just a simple reason why we need a standardized convention in our project source code as software engineers. I think it’s a common problem that needs to be reminded so as a developer we have to keep our code structure clean as has been set.

Why We Need Standardization In Our Project Source Code?

Before we go too far, I think we have to start with “why” first. Why do we need the standardized convention in our code? Here’re the whys.

Every Team Member Has Their Own Code Style

Like I’ve told in the Introduction section when I was making my personal projects, I code for myself so maybe I can use whatever code style I like. But everything changes when I have a full-time job and have to work in a team with several people. Every team member has their own code style and it may be confusing when I got a task and need to understand someone’s code that has a very different style.

Not only me actually, when other teammates read my code, they were also confused with my code style, LOL. This is why we need to make an “agreement” so we can use a consistent code style in our code base.

To Increase Maintainability and Readability

I have been worked at a software house company that has a project-based work culture. Our task is finished when the requested app is delivered to the client.

I was a newbie junior frontend engineer at that time and I code with barbaric style. In my mind, I just have to finish and deliver it to the client before the deadline. That was a dark moment in my career life, hahaha.

The situation changes when I switch jobs to another company and now I’m working in an in-house company that has their own product that needs to be developed. The main focus is change now.

In the previous company, my main focus is just to code and deliver. But in the current company, I also have to think about how to make my code is maintainable so it will be easier to be improved or updated when needed.

The answer is quite simple, make and follow the code convention so the code style in the project code base is consistent even it was developed by different people. The consistent code style makes it readable, and if it’s readable, it will be easier to be maintained.

Not Only Code but Commit Message Also Need To Be Standardized

When working with a team, it’s important to tell the informative message when pushing a commit to the Github (or Gitlab) repository. The best code style is useless if the commit message is bad. Other team members don’t understand the changes that you’ve made, and it can cause confusion and chaos in the future.

Thankfully, there’s Conventional Commit that can help the developers to make a proper commit message before they push their code to the Git Repository.

How To Standardize The Project Source Code?

I’ll tell you based on my experience as a front-end engineer. Luckily there are some tools that can help us to make the code convention. Here’s what I usually use.

For giving an example purpose, I’ve prepared a simple Next.js (Typescript) project. You can use next-tailwind-polos if you want to try to standardize the source code using those tools. You can clone it to your local device and don’t forget to install the dependencies using yarn or npm install

Here’s what we’ll do in the next section:

In the steps below I’ll use yarn, actually, you can just adapt it by your preference if you use npm. You can see the official docs so you can match them by your need.

Prettier Configuration

I assume that you’ve already cloned the example project source code, so I will focus on the tool's functionality.

Make sure you’re open the project folder through VS Code or your terminal, then run yarn add --dev --exact prettier. Then create a file named .prettierrc.json in the root folder, or you can just run echo {}> .prettierrc.json in your terminal.

In the .prettierrc.json file, you can fill the configuration like below or you can fill it by your needs (reference: Prettier Config Options).

{
  "endOfLine": "lf",
  "semi": true,
  "singleQuote": false,
  "tabWidth": 2,
  "trailingComma": "es5"
}

json

Now, you can just run yarn prettier --write [directory scope] to format your code. Or if you use VS Code, you can set Format on Save in your VS Code Settings. You also can use the shortcut to manually format the file (using VS Code) by pressing Shift + Option + F (in MacBook) or Shift + CTRL + F (in Windows).

Configure The Base ESLint Rules

Because we use Next.js we will use ESLint for Next.js. But luckily in the newest Next.js version, it has automatically installed when we initiate the project. So in this case, we just focus on the eslintrc.json file wherein the root project.

But make sure, the lint command exists in the package.json file.

"scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  }
...

json

Here are my ESLint rules in eslintrc.json. You don’t have to imitate this 100%, just match it by your own preference or current needs.

{
  "env": {
    "node": true
  },
  "extends": [
    "next/core-web-vitals",
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended"
  ],
  "parser": "@typescript-eslint/parser",
  "plugins": ["import", "unused-imports", "@typescript-eslint"],
  "settings": {
    "import/resolver": {
      "node": {
        "extensions": [".js", ".jsx", ".ts", ".tsx"],
        "moduleDirectory": ["node_modules", "src/"]
      }
    }
  },
  "rules": {
    "no-unused-vars": "off",
    "@typescript-eslint/no-unused-vars": "off",
    "@typescript-eslint/explicit-module-boundary-types": "off",
    "@typescript-eslint/no-non-null-assertion": "off",
    "@typescript-eslint/no-inferrable-types": "off",
    "@next/next/no-img-element": "off",
    "unused-imports/no-unused-imports": "error",
    "unused-imports/no-unused-vars": [
      "warn",
      {
        "vars": "all",
        "varsIgnorePattern": "^_",
        "args": "after-used",
        "argsIgnorePattern": "^_"
      }
    ],

    "no-eq-null": "warn",
    "import/order": [
      "warn",
      {
        "groups": [
          ["builtin", "external"],
          "internal",
          "parent",
          ["sibling", "index"],
          "object"
        ],
        "newlines-between": "always",
        "alphabetize": {
          "order": "asc",
          "caseInsensitive": true
        }
      }
    ],
    "complexity": "warn",
    "no-console": ["error"]
  }
}

json

In this case, I use third-party ESLint plugins like import, unused-import, and typescript-eslint.

After the config process is finished, you can run yarn lint to check if your code is already matched with the ESLint rules or not. You can also run yarn lint --fix to automatically fix your code based on the rules that have been set. Remember that sometimes we need to manually edit the code, so don’t overly rely on the automated fixing code.

Configure Husky Base Setting

Want some automation addition? I usually use Husky to automate the checking process before committing or pushing to the Github Repository.

Because we’re using yarn, we’ll install it by running npx husky-init && yarn in the terminal. It will automatically generate the prepare command in package.json and a base pre-commit config.

husky install

After that, we’ll install the Lint Staged to trigger and run lines on git staged files by executing npx mrm@2 lint-staged. It will automatically generate the base command triggers in pre-commit husky config file. After that, you can delete or modify the content by your own preference. After that, it will run the linter before the commit process. So you have to make sure that your code is matched with the linter rules.

Lint staged install

Like I’ve mentioned before, not only code, we also need to standardize our commit message before pushing it to the Github repository. So we’ll set Commit Lint by executing yarn add --dev @commitlint/config-conventional @commitlint/cli in the terminal.

Don’t forget to set the commitlint config as our base commit config by running this command in the terminal.

echo "module.exports = { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js

bash

Now integrate the commit lint into the husky config by executing yarn husky add .husky/commit-msg 'yarn commitlint --edit $1' . It will generate a new husky config file named commit-msg.

commit-msg

Now you cannot make any “barbaric” commit message anymore, LOL.

commitlint

Want to add some additional config before pushing your code to Git Repository? For example, I run npx husky add .husky/pre-push 'yarn lint' to generate the husky config that triggers the linter before pushing my code.

pre-push

And YEAH!!! IT’S FINISHED. Note that, you don’t have to imitate my method 100%. You can match it with your needs.

Closing

Actually, this is not an absolute way. There are so many ways or even tools that also help us to standardize our source code. Hope it helps you guys. I’m sorry if still there’s some grammar error. I’m still learning how to write in English properly, hahaha. Let me know if you want to discuss something in the comment section.

Back To Articles Page
Home
Projects
Articles
About Me