📜 ⬆️ ⬇️

Prettier, ESLint, Husky, Lint-Staged and EditorConfig: neat code writing tools

You strive to write neat code, but you don’t know where to start ... You read the style manuals like Airbnb, try to follow the practical recommendations of leading experts ... Do you have to delete unused code? Have to look for unnecessary variables? Are you trying to identify unsuccessful patterns used in your programs? For example, if you want to understand, by reading the intricacies of the code of a certain function, whether it will return something or not. Sounds familiar? The problem is that it is very hard for a programmer to do a lot and learn a lot.

Maybe you are a team leader, under whose leadership a team of developers of different levels is working? Are there new people in your team? Are you worried that the code they write will not meet your standards? Are your days in checking someone else's code when these checks mainly concern compliance with standards, not program logic?


')
The author of this material says that he came across everything that the questions just asked are devoted to. What he encountered is exhausting and exhausting. Here he wants to talk about the tools, the correct application of which allows to solve the problems described above.

Namely, here we will talk about such means as Prettier, ESLint, Husky, Lint-Staged, EditorConfig, about automating formatting and lint code. This material is mainly focused on React-development, but the principles discussed here can be applied in any web project. Here is the repository, where, among other things, collected what is going to be discussed here.

Prettier


Prettier is a tool for formatting code that aims to use hard-coded rules for the design of programs. It formats the code automatically. Here's what it looks like.


Prettier formats the code by following the rules.

▍ Strengths Prettier


Here are the features and features of Prettier that allow us to talk about the usefulness of this tool:


▍Set Up Prettier


Here's how to use Prettier in a new project. Create an app folder, and, after going to it, run the following command at the command prompt:

 npm init -y 

With this command, npm initializes a new project in the app folder by creating the package.json file in it.

I will use yarn in this material, but npm can also be used here. Prettier can be connected to an existing project.

Install the prettier package as a dependency on the development of our project:

 yarn add --dev prettier 

Thanks to this command, a development dependency entry will be added to package.json , which looks like this:

 { "name": "react-boiler-plate", "version": "1.0.0", "description": "A react boiler plate", "main": "src/index.js", "author": "Adeel Imran", "license": "MIT", "scripts": {   "prettier": "prettier --write src/**/*.js" }, "devDependencies": {   "prettier": "^1.14.3" } } 

We’ll talk about what the "prettier": "prettier — write src/**/*.js" line means "prettier": "prettier — write src/**/*.js" . In the meantime, let's create the src folder in the app folder. In this folder, create the file index.js , although you can name it as you like.

Into this file we will add the following code (in exactly this unsightly form):

 let person =                     { name: "Yoda",               designation: 'Jedi Master '               };             function trainJedi (jediWarrion) { if (jediWarrion.name === 'Yoda') { console.log('No need! already trained'); } console.log(`Training ${jediWarrion.name} complete`)             } trainJedi(person)             trainJedi({ name: 'Adeel',             designation: 'padawan' }); 

So, at the moment we have a file src/app/index.js , in which there is a rather poorly designed code.

How to fix it? There are three approaches to working with poorly formatted code:

  1. Manually format this code.
  2. Use an automated tool.
  3. Leave everything as it is and continue to work (please do not choose this approach).

I'm going to choose the second option. Now in our project there is a corresponding dependency, and, moreover, in the scripts section of the package.json file there is an entry about Prettier. It is clear that we will use this tool to format the code. To do this, create a prettier.config.js file in the app folder and add the rules for Prettier:

 module.exports = { printWidth: 100, singleQuote: true, trailingComma: 'all', bracketSpacing: true, jsxBracketSameLine: false, tabWidth: 2, semi: true, }; 

Let's sort these rules:


 <button className="prettier-class" id="prettier-id" onClick={this.handleClick}> Click Here </button> 

Here is what happens if it is set to false :

 <button className="prettier-class" id="prettier-id" onClick={this.handleClick} > Click Here </button> 


Here you can find information on all the rules of Prettier.

Now that the rules are configured, let's talk about this script:

 "prettier": "prettier  — write src/**/*.js" 

Thanks to this construction, Prettier runs and finds all .js files in the src folder. The --write flag instructs him to save formatted files as they are processed and corrected for formatting errors found in them.

Run the script from the command line:

 yarn prettier 

This is what happened after this with the poorly formatted code shown above.


Result of code formatting with Prettier

At this point, we will assume that we figured out with Prettier. Let's talk about linters.

Eslint


Lint is a type of static code analysis that is often used to find problem design patterns or code that does not follow certain style guidelines.

There are linters intended for most programming languages, sometimes compilers include lint in the code compilation process. This definition of lint is taken from the ESLint JavaScript open source information liner information page , which we'll talk about.

▍Why need a linter for javascript?


Since JavaScript is a dynamic programming language with weak typing, the code written on it is prone to errors made by developers. JavaScript is an interpreted language, so syntax and other errors in the code are usually detected only after running this code.

Linters, like ESLint , allow developers to find problems in the code without starting it.

▍Why is ESLint a special tool?


The heading of this section has a good question. The point here is that ESLint supports plugins. So, the code verification rules should not be a monolithic package. Everything you need, you can connect as needed. Each lint rule added to the system is autonomous, it can be, independently of the others, on or off. Each rule can be assigned an alert level in accordance with the desire of the developer - this can be a warning (warning) or an error (error).

When using ESLint, you are working with a fully customizable system that can reflect your understanding of what the correct code should look like, and record what set of rules you follow.

Among the existing JavaScript style guides, the following are very popular:


I, as already mentioned, use the Airbnb style guide. I was advised by this document to be my manager at the company where my professional career began, and I consider this style guide to be my most valuable asset.

This tutorial is actively maintained — take a look at its GitHub repository. Here I will use a set of rules based on it.

Now let's work on the package.json file, add some dependencies to it:

 { "name": "react-boiler-plate", "version": "1.0.0", "description": "A react boiler plate", "main": "src/index.js", "author": "Adeel Imran", "license": "MIT", "scripts": {   "lint": "eslint --debug src/",   "lint:write": "eslint --debug src/ --fix",   "prettier": "prettier --write src/**/*.js" }, "husky": {   "hooks": {     "pre-commit": "lint-staged"   } }, "lint-staged": {   "*.(js|jsx)": ["npm run lint:write", "git add"] }, "devDependencies": {   "babel-eslint": "^8.2.3",   "eslint": "^4.19.1",   "eslint-config-airbnb": "^17.0.0",   "eslint-config-jest-enzyme": "^6.0.2",   "eslint-plugin-babel": "^5.1.0",   "eslint-plugin-import": "^2.12.0",   "eslint-plugin-jest": "^21.18.0",   "eslint-plugin-jsx-a11y": "^6.0.3",   "eslint-plugin-prettier": "^2.6.0",   "eslint-plugin-react": "^7.9.1",   "husky": "^1.1.2",   "lint-staged": "^7.3.0",   "prettier": "^1.14.3" } } 

Before talking about how to work with this configuration, I want to focus on the dependencies of the project that are added to package.json . I believe that before using certain dependencies, it is worth knowing what role they play.

Therefore, we will discuss the role of the packages presented here:


In this article, we are not talking about testing the code, but package.json presented above has dependencies intended for unit testing using Jest / Enzyme . Here, if you decide to use these tools for testing, a description of the relevant packages.


There are a couple more packages in the file, which we will discuss later, discussing automation issues. It is husky and lint-staged .

Now that we have, in general terms, discussed our tools, we will continue to work.
Create a .eslintrc.js file in the app folder:

 module.exports = {   env: {       es6: true,       browser: true,       node: true,   },   extends: ['airbnb', 'plugin:jest/recommended', 'jest-enzyme'],   plugins: [       'babel',       'import',       'jsx-a11y',       'react',       'prettier',   ],   parser: 'babel-eslint',   parserOptions: {       ecmaVersion: 6,       sourceType: 'module',       ecmaFeatures: {           jsx: true       }   },   rules: {       'linebreak-style': 'off', //    Windows.       'arrow-parens': 'off', //   prettier       'object-curly-newline': 'off', //   prettier       'no-mixed-operators': 'off', //   prettier       'arrow-body-style': 'off', //  -   ?       'function-paren-newline': 'off', //   prettier       'no-plusplus': 'off',       'space-before-function-paren': 0, //   prettier       'max-len': ['error', 100, 2, { ignoreUrls: true, }], // airbnb           'no-console': 'error', // airbnb         'no-alert': 'error', // airbnb         'no-param-reassign': 'off', //  -   ?       "radix": "off", // parseInt, parseFloat  radix .    .       'react/require-default-props': 'off', // airbnb           'react/forbid-prop-types': 'off', // airbnb           'react/jsx-filename-extension': ['error', { extensions: ['.js'] }], // airbnb  .jsx       'prefer-destructuring': 'off',       'react/no-find-dom-node': 'off', //           'react/no-did-mount-set-state': 'off',       'react/no-unused-prop-types': 'off', //            'react/jsx-one-expression-per-line': 'off',       "jsx-a11y/anchor-is-valid": ["error", { "components": ["Link"], "specialLink": ["to"] }],       "jsx-a11y/label-has-for": [2, {           "required": {               "every": ["id"]           }       }], //     htmlFor  label       'prettier/prettier': ['error'],   }, }; 

Now add the .eslintignore file to the app folder:

 /.git /.vscode node_modules 

Now let's talk about how the .eslintrc.js file is .eslintrc.js , and about the meaning of the constructions presented in it.

This file has the following structure:

 module.exports = {  env:{},  extends: {},  plugin: {},  parser: {},  parserOptions: {},  rules: {}, }; 

Consider the blocks of this file, represented by objects with the appropriate names:


Now let's talk about the .eslintignore file. This file accepts a list of paths representing folders whose contents should not be processed using ESLint.

Here are three folders:


Now consider a couple of new scripts, which appeared in package.json . Here they are:

 "lint": "eslint --debug src/" "lint:write": "eslint --debug src/ --fix" 

If you execute the first one, using the yarn lint or npm run lint command, this will cause the linter to scan all the files in the src directory and display a detailed report on the files in which it found errors. Using this report, you can correct these errors.


Run lint script

If you run the second script ( yarn lint:write ), then ESLint will perform the same test that was performed before. The only difference is that in this mode the system will try to correct the detected errors, will try to bring the code into a more decent view.

ESLint extension for VS Code


We already have Prettier and ESLint configured, but to use the capabilities of these tools, we have to run scripts. This is not very convenient, so try to fix it. Namely, we want to ensure that the formatting and linting code would be performed by the command to save the file in the editor. In addition, we want to lint and format the code before committing.

We, as an example, use the VS Code editor. We will need the ESLint extension for VS Code. In order to install it, you can open the VS Code extension panel ( ctrl+shift+x ). Here, in the search field, you must enter eslint . A list of extensions appears. We are interested in that, in the information on the developer of which Dirk Baeumer is specified. After installing this extension, restart the editor.

Now, in the root folder of the project ( app ), create a .vscode folder (note the dot at the beginning of the name - this is important). In this folder, create a file settings.json following content:

 { "editor.formatOnSave": false, "eslint.autoFixOnSave": true, } 

Consider its contents.


It is important to note that now that the lint:write script is run, it will execute both the linting and formatting of the code.

Imagine your feelings if you had a project code of 20,000 lines in size that you should check and improve. Now imagine that you would have to do it manually. Such work would probably take a month. And with the help of the above automation, all this is done in about thirty seconds.

Now, after setting up all the necessary, every time you save a file with a code, the editor will take care of checking and formatting the program text. However, here we are talking about the VS Code editor. It is possible that someone on your team prefers some other editor. There is nothing wrong with this, but in order for everyone to work comfortably, we will have to work on something else to automate.

Husky


The Husky package allows you to enable Git hooks. This means that you have the opportunity to perform certain actions before performing a commit or before sending the repository code.

To take advantage of the Husky features, first install this package:

 yarn add --dev husky 

After that, add the following to package.json :

 "husky": {     "hooks": {         "pre-commit": "YOUR_COMMAND_HERE",    "pre-push": "YOUR_COMMAND_HERE"    } }, 

This will lead to the fact that before executing the commit or push command, a certain script will be called, which, for example, performs testing of the code or its formatting.

You can read more about Husky here .

Lint-staged


The Lint-staged package allows you to check indexed files with a linter, which helps to prevent the code from being sent to the repository with errors.

Lingting makes sense to commit to the code. Thanks to this, you can make sure that errors do not penetrate the repository, and provide a uniform styling of the code that goes there. However, performing a lint to validate the entire project may be too time consuming, and the results of such a check may be meaningless. Ultimately, it may be necessary to expose the files you plan to commit to linting.

Lint-staged allows you to perform a set of arbitrary tasks on indexed files filtered by a search pattern. Details about this can be found here .

Install the Lint-staged package:

 yarn add --dev lint-staged 

Then, in the package.json file, add the following:

 "lint-staged": {     "*.(js|jsx)": ["npm run lint:write", "git add"] }, 

Due to this construction, the lint:write command will first be executed, checking the file contents and correcting errors, after which the files will be added to the index using the git add command. This command now targets .js and .jsx files, but you can do the same with other file types.

Sharing Husky and Lint-staged


Consider the action plan that allows you to organize the next workflow. Each time you commit files with a code, before performing this operation, the system runs the lint-staged script, which, in turn, runs the lint:write script, which performs the linting and code formatting. After that, the files are added to the index, and then committed. It seems to me that it is very convenient. In fact, in the previously presented code of the package.json file, this is already implemented, we just did not talk about this before.

Here is again, for convenience, the contents of our package.json :

 { "name": "react-boiler-plate", "version": "1.0.0", "description": "A react boiler plate", "main": "src/index.js", "author": "Adeel Imran", "license": "MIT", "scripts": {   "lint": "eslint --debug src/",   "lint:write": "eslint --debug src/ --fix",   "prettier": "prettier --write src/**/*.js" }, "husky": {   "hooks": {     "pre-commit": "lint-staged"   } }, "lint-staged": {   "*.(js|jsx)": ["npm run lint:write", "git add"] }, "devDependencies": {   "babel-eslint": "^8.2.3",   "eslint": "^4.19.1",   "eslint-config-airbnb": "^17.0.0",   "eslint-config-jest-enzyme": "^6.0.2",   "eslint-plugin-babel": "^5.1.0",   "eslint-plugin-import": "^2.12.0",   "eslint-plugin-jest": "^21.18.0",   "eslint-plugin-jsx-a11y": "^6.0.3",   "eslint-plugin-prettier": "^2.6.0",   "eslint-plugin-react": "^7.9.1",   "husky": "^1.1.2",   "lint-staged": "^7.3.0",   "prettier": "^1.14.3" } } 

Now that you know Husky and Lint-staged, you can evaluate their impact on working with Git. Namely, suppose that the following commands were executed:

 $ git add . $ git commit -m "some descriptive message here" 

It is clear that before the commit, the code will be checked for compliance with the rules specified in .eslintrc.js , and, if necessary, corrected. Thanks to this, the errors will never get to the working project repository.

Now you know how to integrate Prettier, ESLint, Husky and Lint-staged into your project.

Let me remind you that we have said above that not all members of your team use my favorite VS Code. In order for all of them to work comfortably, we will need to deal with the .editorconfig file.

.Editorconfig file


Different members of your team can use different editors. Forcing them to use any one editor comes to nothing. However, in order for everyone to use the same settings regarding, for example, indents or line feeds, we use the file. editorconfig . It helps maintain a single set of rules in heterogeneous teams.

, . , , WebStorm, AppCode, Atom, Eclipse, Emacs, BBEdit .

app .editorconfig :

 # EditorConfig -  : http://EditorConfig.org #  EditorConfig   root = true [*.md] trim_trailing_whitespace = false [*.js] trim_trailing_whitespace = true #     Unix       [*] indent_style = space indent_size = 2 end_of_line = lf charset = utf-8 insert_final_newline = true max_line_length = 100 

, :


Results


, , , . , , .

Dear readers! ? ?

Source: https://habr.com/ru/post/428173/


All Articles