preface

Some time ago, I took over a new project and found that the code writing style was very different from mine. For example, the indentation of JS files was 2 Spaces, but the indentation of CSS was 4 Spaces. JSX is also written in a strange way:

<Modal
  title={intl.get("export")}
  onRequestClose={this.closeExportHitModal}>
  hello world
</Modal>
Copy the code

The official way to write it is:

<Modal
  title={intl.get("export")}
  onRequestClose={this.closeExportHitModal}
>
  hello world
</Modal>
Copy the code

There are also files where a single line of code contains a lot of content that can be broken down into two or more lines and read much more clearly. In short, the whole project looked chaotic, with various writing styles mixed together, which was not conducive to project maintenance. Right now, I’m working on the project alone, and the best way to do that is to adapt the project to a unified writing style, and then someone else can code to that rhythm and style. But the problem is that I can’t guarantee that everyone thinks the same way as I do. The best way is to use the tool to restrict everyone’s writing style, so that when writing, you don’t have to worry about style, and finally when submitting, the style is consistent.

There are many known js code styles and validation tools, such as JsLint, JSHint, JSCS and ESLint; Prettier is the most popular tool for coding style classes. In fact, the two tools overlap when they are used. So how to choose, how to use, how to draw boundaries between tools, how to deal with conflicts and so on all come to mind. Don’t worry. Let’s take it one by one.

Desired effect

Before looking at specific tools, we need to take stock of our inner needs, formulate a clear thought and goal, and then work towards that goal.

Automatic execution rather than manual execution

When I took over the project, ESLint was already in use in the project, but as a separate NPM script, implemented by executing this script and not automatically implemented at Git commit time. So I expect to be able to automate checking and code styling via git hooks. At the same time, if ESLint reports an error, it terminates the COMMIT and prints a report telling the writer which files and where the error occurred. This requires husky, a Tool related to Git hooks.

Do incremental code instead of all the code already in the project

At the same time, when I took over, the project had already reached a certain scale, so I did not want to conduct code inspection and uniform style treatment for all the codes of the whole project. In the absence of testing, this can cause unexpected problems. So you only want automated verification and uniform processing for incremental code. This requires another tool: Lint-staged.

Which does the Lint tool use?

There are many js lint tools, which one should I use? I expect it to be configurable and support JSX syntax, and to be constantly updated, because JS syntax changes so quickly that if you just support the old syntax, it will soon become unusable. So I need to compare different Lint tools and choose the one that ends up meeting expectations.

Final desired effect

Based on the above expectations, the final comprehensive effect to be achieved is:

At Git commit time, check, validate, and beautify incremental commit code using git hooks. When you automate Lint, if you find an error, you can display the error message and abort the COMMIT so that the writer can fix the error. If there are no errors, just beautify and submit the code.

Detailed tool

Each tool looks simple, but there are a lot of pitfalls. Now let’s explain them all.

eslint

Here’s a helpful answer from Stackoverlow to understand Lint:

Linting is the process of running a program that will analyse code for potential errors.

So the process of Lint is to find suspicious problems and resolve those suspicious processes. Js has a lot of lint tools. Why use ESLint and not another Lint tool? You can refer to this article.

In summary: ESLint is configurable, extensible, and pluginable. It is compatible with JSX and many new JS syntax through plug-in. Eslint is the most powerful and reliable of all JS Lint tools.

prettier

At first glance, it seems that esLint already has code style-related configuration items, such as max-len, which has a number of related configuration items, maximum number of lines of code, tabWidth, etc. So why prettier? Prettier’s website explains:

Linters have two categories of rules: Formatting rules: eg: max-len, no-mixed-spaces-and-tabs, keyword-spacing, comma-style… Prettier alleviates the need for this whole category of rules! Prettier is going to reprint the entire program from scratch in a consistent way, so it’s not possible for the programmer to make a mistake there anymore 🙂

Code-quality rules: eg no-unused-vars, no-extra-bind, no-implicit-globals, prefer-promise-reject-errors… Prettier does nothing to help with those kind of rules. They are also the most important ones provided by linters as they are likely to catch real bugs with your code!

For clarity, Linters provide two types of checks for style-related formatting rules and code quality rules. Prettier, on the other hand, only cares about the former type of rules, formatting rules related to code style. Why does EsLint need Prettier? Because ESLint’s rules are configurable, there are so many configurable items. If you want to really use it your way, you need to go through an API, which is too laborious to use. Prettier is an opinionated code formatter, an opinionated code formatter that is subjective, even somewhat arbitrary.

Prettier’s why Prettier and Option finsophy explain why prettier does so

By far the biggest reason for adopting Prettier is to stop all the on-going debates over styles. It is generally accepted that having a common style guide is valuable for a project and team but getting there is a very painful and unrewarding process. People get very emotional around particular ways of writing code and nobody likes spending time writing and receiving nits.

The more options Prettier has, the further from the above goal it gets. The debates over styles just turn into debates over which Prettier options to use.

That said, everyone was willing to agree on a code style, but the problem was that there was a lot of debate about which style to use, and reaching agreement was actually a very thankless task. Prettier is opinionated, unwilling to add too many configuration items to please anyone. So Prettier leaves very little room for configuration. You can use it if you want.

Prettier and ESLint since Prettier and ESLint overlap, there must be conflicts when used, how to handle them, where to draw the line, and how to configure Prettier and ESLint in detail later on. Prettier actually did the same thing.

husky

To link to Git hooks, we need husky. To use it, configure a husky item in package.json:

"husky": {
  "hooks": {
    "pre-commit": "lint-staged"
  }
}
Copy the code

Pre-commit can be followed by any command, such as NPM run lint or something like this. Lint-staged commands have been configured because I used Lint-staged commands.

There is a bug in husky, which is the result of hooks not working on husky.

Husky’s Changelog says so.

(husky 3.0.0)Breaking change husky requires now Git >= 2.13.2

Husky requires git version >= 2.13.2 as of 3.0.0. So if husky is not working, check to see if husky meets git’s version requirements. The solution can be to upgrade git versions or degrade Husky. The current husky project is very simple and is based on the git versions of most project members. I chose to downgrade Husky to V2.7.0.

lint-staged

Lint-passage is used to describe lint-passage files.

Run linters against staged git files and don’t let 💩 slip into your code base!

Lint-staged configuration is also simple, configured in package.json:

{
  "lint-staged": {
    "*": "your-cmd"
  }
}
Copy the code
  • Replace with the file to check and your-cmd with the command you want to execute. According to our requirements, our configuration item is

    “lint-staged”: { “*.{js,jsx}”: [ “eslint –fix”, “git add” ] }

That is, check with ESLint, fix the fix directly, git add, and commit. If an error is found during esLint –fix, an error will be reported and the commit will be cancelled.

We can perform different checks for different file types, for example:

Stackoverflow.com/questions/5…

  "lint-staged": {
    "*.{js,jsx}": [
      "eslint --fix",
      "prettier --write",
      "git add"
    ],
    "*.{md}": [
      "prettier --write",
      "git add"
    ]
  }
Copy the code

Integrate all tools

Husky and Lint-staged usage is already clear from all the tools described above, just configure the following in package.json.

 "husky": {
   "hooks": {
     "pre-commit": "lint-staged"
   }
 },
 "lint-staged": {
   "*.{js,jsx}": [
     "eslint --fix",
     "git add"
   ]
 }
Copy the code

Prevlantless JS/JSX files that have been added into some passively written JS/JSX files (esLint –fix) will be executed at COMMIT time. Git Add then git commit If not, display an error message and stop commit.

But how do esLint and Prettier fit together? Prettier’s website shows the solution.

Whatever linting tool you wish to integrate with, the steps are broadly similar. First disable any existing formatting rules in your linter that may conflict with how Prettier wishes to format your code. Then you can either add an extension to your linting tool to format your file with Prettier – so that you only need a single command for format a file, or run your linter then Prettier as separate steps.

The first step is to disable all code formatting rules in Linter that conflict with Prettier. Prettier can then be used prettier in two ways, by adding an extension to linter. The other is to split Lint and Prettier into two steps, using Linter first and then prettier to process the code behind Linter.

The article also gives a solution for how ESLint can merge. Just use it.

Step 1: Disable formatting rules in ESLint

It would be too cumbersome to disable one by one manually, using eslint-config-prettier instead.

eslint-config-prettier is a config that disables rules that conflict with Prettier. Add it to your devDependencies, then extend from it within your .eslintrc configuration. Make sure to put it last in the extends array, so it gets the chance to override other configs.

Step 2: Use Prettier in ESLint

eslint-plugin-prettier is a plugin that adds a rule that formats content using Prettier. Add it to your devDependencies, then enable the plugin and rule.

In other words, eslint-plugin-prettier can support prettier in ESLint. But the website directly provides a comprehensive solution of the above two steps.

eslint-plugin-prettier exposes a “recommended” configuration that configures both eslint-plugin-prettier and eslint-config-prettier in a single step. Add both eslint-plugin-prettier and eslint-config-prettier as developer dependencies, then extend the recommended config:

Installing eslint-config-prettier and eslint-plugin-prettier in ESLint

{
  "extends": ["plugin:prettier/recommended"]
}
Copy the code

That’s it; you don’t need to configure config and plugins separately.

Finally, my ESLint configuration uses.eslintrc as follows:

 {
   "parser": "babel-eslint",
   "parserOptions": {
     "ecmaFeatures": {
       "legacyDecorators": true
     }
   },
   "extends": ["standard", "standard-react", "plugin:prettier/recommended"],
   "plugins": ["babel", "react", "promise"],
   "env": {
     "browser": true
   },
   "globals": {
     "__DEV__": false,
     "__TEST__": false,
     "__PROD__": false,
     "__COVERAGE__": false
   },
   "rules": {
     "no-unused-vars": "error",
     "react/prop-types": ["warn"],
     "camelcase": ["warn"]
   }
 }
Copy the code

The installation package includes:

"Babel - eslint" : "^ 9.0.0", "eslint" : "^ 6.4.0", "eslint - config - prettier" : "^ 6.2.0", "eslint - config - standard" : "^ 6.0.0 eslint - config -", "standard - the react" : "^ 4.0.0", "eslint - plugin - Babel" : "^ 4.0.0", "eslint - plugin - prettier" : "^ 3.1.0 eslint -", "plugin - the promise", "^ 3.0.0", "eslint - plugin - react" : "^ 6.0.0", "eslint - plugin - standard" : "^ 2.0.0",Copy the code

The above configuration is for reference only.

conclusion

The specification is constrained only by artificial training or documentation, and is practically unreliable. Only through such automated tools can true and reliable unification be achieved. In fact, this is the biggest harvest I have gained from doing this, so in the future work, I will try to use tools to restrain as much as possible, rather than relying on tacit understanding and oral agreement.