Set up ESlint, Prettier & EditorConfig without conflicts
This article is the second in a series on how to enhance your development environment using ESLint, Prettier, and EditorConfig.
If you still have questions about the use of these three tools, you can read my first article why Should You Use ESLint, Prettier, and EditorConfig? . The goal of this article is to provide guidelines for conflict-free configuration of ESLint, Prettier, and EditorConfig while avoiding unnecessary configuration.
background
If you already use Prettier with ESLint, you might run into code formatting problems.
I encountered these problems at work when we decided to migrate TSLint from a TypeScript project to ESLint. The idea was to upgrade code detection by using ESLint and Prettier together. We fixed this problem with the ESLint rule that enforces two space indents. But other conflicts arose. Obviously, we can’t fix conflicts by adding ESLint rules to every conflict.
Solve the model
As discussed in the previous article, we want to use a specialized approach. In this case, ESLint becomes our code quality detector, Prettier acts as a code formatting tool, and EditorConfig will provide the correct editor configuration for everyone.
- All configuration related to the editor (closing line, indent style, indent size, and so on) should be handled by EditorConfig.
- Everything related to code formatting should be handled by Prettier.
- ESLint takes care of the rest (code quality).
ESLint & Prettier
For the rest of this article, we’ll use the code we wrote in the first article. To summarize, we have a main.js file with an ESLint configured and installed Prettier.
// main.js
function printUser(firstName, lastName, number, street, code, city, country) {
console.log(`${firstName} ${lastName} lives at ${number}.${street}.${code} in ${city}.${country}`);
}
printUser('John'.'Doe'.48.'998 Primrose Lane'.53718.'Madison'.'United States of America');
Copy the code
//.eslintrc.json (json files do not support comments)
{
"extends": ["eslint:recommended"]."env": {
"es6": true."node": true}}Copy the code
Prettier, go to work
3, In order to use ESLint with Prettier, disable all ESLint rules (only code formatting rules) that would conflict with Prettier. Fortunately, the eslint-config-Prettier package already does this for us.
npm install eslint-config-prettier --save-dev
Copy the code
Json file to add prettier to the extends array and remove all of our existing code formatting rules:
{
"extends": ["eslint:recommended"."prettier"]."env": {
"es6": true."node": true}}Copy the code
The prettier configuration overwrites some of the previous extends array configuration and disallows all ESLint code formatting rules. With this configuration, Prettier and ESLint can run peacefully alone.
ESLint integration Prettier
Having to run two commands to detect and format files is very inconvenient. To solve this problem, we’ll make ESLint integrate Prettier by adding the eslint-plugin-Prettier package.
npm install eslint-plugin-prettier --save-dev
Copy the code
Json file, add the prettier plug-in to plugins and set the new prettier rule to error so that prettier formatting errors become ESLint errors.
{
"extends": ["eslint:recommended"."prettier"]."env": {
"es6": true."node": true
},
"rules": {
"prettier/prettier": "error"
},
"plugins": [
"prettier"]}Copy the code
We then apply the untested main.js to ESLint:
npx eslint main.js
Copy the code
Prettier /prettier in error output from ESLint, we can see lines where there are too many characters or where there is a problem with indentation being marked as an error by prettier/prettier.
Now let’s use ESLint’s fix options:
npx eslint main.js --fix
Copy the code
You’ll see our file formatted the way Prettier does.
Through. Eslintrc. Json file extends array to add the plugin: prettier/it configuration, you can replace we have all the prettier related configuration Settings.
It looks like this:
//.eslintrc.json (json files do not support comments)
{
"extends": ["eslint:recommended"."plugin:prettier/recommended"]."env": {
"es6": true."node": true}}Copy the code
This configuration has the same effect as the previous one, but is shorter and less explicit. For clarity, we will use the original configuration for the rest of the article.
The “chasm” between Prettier and ESLint
Add an ESLint plugin
This is enough for small projects like this, but once you start using Vue, React, or other frameworks, it’s easy to confuse ESLint with Prettier. A common problem I see is developers adding an ESLint plug-in, expecting it to work, without adding anything else to make Prettier work too.
In the case of TypeScript
At some point, we decided to use TypeScript in the above project. Since TSLint would soon be deprecated, we decided to replace it with ESLint. We’ll take TypeScript as an example. What we did below also applies to React, Vue, or any other framework with the ESLint plugin available.
Here is the main.ts file from main.js:
function printUser(firstName: string, lastName: string.number: number, street: string, code: number, city: string, country: string) :void {
console.log(`${firstName} ${lastName} lives at The ${number}.${street}.${code} in ${city}.${country}`);
}
printUser('John'.'Doe'.48.'998 Primrose Lane'.53718.'Madison'.'United States of America');
Copy the code
In order for ESLint to be compatible with TypeScript or other frameworks with a specific syntax, we need to add a parser so that ESLint can read the new code added to the plugin and a new set of rules associated with TypeScript (or any other framework that requires a parser).
npm install typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev
Copy the code
We then modify the.eslintrc.json file to include TypeScript by adding a TypeScript parser to the Parser option and a plug-in to the extends array:
{
"parser": "@typescript-eslint/parser"."extends": ["plugin:@typescript-eslint/recommended"."eslint:recommended"."prettier"]."env": {
"es6": true."node": true
},
"rules": {
"prettier/prettier": "error"
},
"plugins": [
"prettier"]}Copy the code
Then, we run ESLint on the file using the fix option:
If we run this command multiple times, we will receive the same error even though the console shows that the error can be fixed. The document did change:
function printUser(
firstName: string,
lastName: string.number: number,
street: string,
code: number,
city: string,
country: string
) :void {
console.log(
`${firstName} ${lastName} lives at The ${number}.${street}.${code} in ${city}.${country}`
);
}
printUser(
'John'.'Doe'.48.'998 Primrose Lane'.53718.'Madison'.'United States of America'
);
Copy the code
Prettier did format our code, but somehow ESLint wanted to indent four Spaces and got two from Prettier. The error looks like it came from the @typescript-esLint rule.
If, like me, you use VSCode and have ESLint’s save time auto-fix option enabled, the problem looks like this:
Resolve conflicts by disabling all ESLint formatting rules for new plug-ins
A common mistake many people make at this point is to solve this or any other conflict with Prettier after the introduction of a new plug-in by overwriting the rules that cause it. The above error is caused by the indentation rule of @typescript-esLint. To fix it, they added this rule to the rules array:
"@typescript-eslint/indent": ["error".2]
Copy the code
While matching Prettier by forcing typescript-esLint to indent effectively solves the current problem, two new problems arise.
- So far, we have only one indentation problem, but we don’t know
typescript-eslint
Is there any other rule in the plug-in that conflicts with Prettier? - Now ESLint and Prettier will both be in charge of formatting our code, which is not in keeping with the problem-solving model we want to follow.
If we follow the previous resolution pattern, ESLint should not be involved in code formatting, and new plug-ins are no exception. Therefore, we need to disable code formatting rules for all new plug-ins by adding the prettier/ @typescript-esLint configuration to the extends array.
{
"parser": "@typescript-eslint/parser"."extends": ["plugin:@typescript-eslint/recommended"."eslint:recommended"."prettier"."prettier/@typescript-eslint"]."env": {
"es6": true."node": true
},
"rules": {
"prettier/prettier": "error"
},
"plugins": [
"prettier"]}Copy the code
Keep in mind that the order of the extends array of.eslintrc.json is very important. Basically, every time a new configuration is added to the array, it overwrites the previous configuration. Therefore, it is important for Prettier and prettier/ @typescript-esLint to be at the end of arrays.
With these configurations, there will be no more problems. Rest assured, ESLint will not try to do Prettier’s job again.
To summarize this FAQ:
- Whenever you add a plug-in to ESLint, you must consider the code formatting rules it brings with it and add a prettier configuration (if one exists) to disable it all. In our example, we used
prettier/@typescript-eslint
But you can use itprettier/react
或prettier/vue
. Please refer toEslint – config – prettier documentTo get a list of supported ESLint plugins. - Don’t try to be yourself
.eslintrc.json
Overwriting formatting rules in files (this is not what ESLint does). - If you find that your code conflicts Prettier and ESLint formatting in two different styles, then you have a useless ESLint formatting rule that causes the conflict, then you are not following the solution described above.
Add a custom rule
Let’s say for our project above, the team is not happy with the two-space indentation and wants four Spaces. A common mistake is to forget our eslint-prettier schema and apply it in a.eslintrc.json file like this:
{
"parser": "@typescript-eslint/parser"."extends": ["plugin:@typescript-eslint/recommended"."eslint:recommended"."prettier"."prettier/@typescript-eslint"]."env": {
"es6": true."node": true
},
"rules": {
"prettier/prettier": "error"."@typescript-eslint/indent": ["error".4]},"plugins": [
"prettier"]}Copy the code
If you’re following along, you shouldn’t be surprised by the generated error. We’re in the same situation:
There are two problems:
- Since our custom rules are in our own
.eslintrc.json
的rules
Array, so it overrides the one responsible for disabling all formatting rulesprettier/@typescript-eslint
The configuration. - Again, by adding this rule, we simply forget Prettier and violate our solution.
To follow this pattern, set all code formatting rules in the.prettierrc configuration file for Prettier. In this case, we should now add one:
// .prettierrc
{
"tabWidth": 4
}
Copy the code
Prettier now formats code with four Spaces instead of the default two, and the.eslintrc.json file should contain no rules for indentation.
To summarize:
- Whenever you want to add a rule, try to categorize it between code quality and code format. An easy way to do this is to check if Prettier enforces the rule.
- Do not add custom formatting rules to
.eslintrc.json
File. These would almost certainly conflict with Prettier.
Prettier & EditorConfig
Set the editor configuration
EditorConfig allows us to have the same editor configuration no matter what editor we use. So every time we write new code, we don’t have to rely on Prettier to format our code according to the team’s conventions. But it does require you to install the necessary EditorConfig plug-ins or extensions on the IDE.
We’ll use VSCode in this article, but remember that EditorConfig supports multiple editors.
We added a custom editor configuration to the project:
# .editorconfig
[*]
end_of_line = lf
charset = utf-8
indent_style = space
Copy the code
If you use the EditorConfig VSCode extension, the editor will know how to format the file. You’ll notice this in the bottom right of the editor:
Avoid duplication of EditorConfig and Prettier
This means Prettier and EditorConfig share configuration items that we don’t want to repeat in two separate files and keep them in sync (e.g., trailing configuration). The most recent version of Prettier solves this problem by parsing the.editorConfig file to determine the configuration options to use.
These options are limited to:
end_of_line
indent_style
indent_size/tab_width
max_line_length
Copy the code
These configuration options override the following Prettier options (if they are not defined in.prettierrc) :
"endOfLine"
"useTabs"
"tabWidth"
"printWidth"
Copy the code
As with ESLint and Prettier, if you change a configuration, the rule is to check if it is related to EditorConfig or Prettier and then make the change in the appropriate file. Previous configuration options other than these four options are only written to.editorConfig.
If you’ve been following this article, you’ve probably noticed a configuration error at this point. For Prettier, we changed the indentation size in the configuration file because it is an editor redundancy, so we should put it in the.EditorConfig file.
# .editorconfig
tab_width 4
Copy the code
Remove the.prettierrc.json file, then run ESLint on unformatted code:
function printUser(
firstName: string,
lastName: string.number: number,
street: string,
code: number,
city: string,
country: string
) :void {
console.log(
`${firstName} ${lastName} lives at The ${number}.${street}.${code} in ${city}.${country}`
);
}
printUser(
"John"."Doe".48."998 Primrose Lane".53718."Madison"."United States of America"
);
Copy the code
The code is indented 4. Now, every time you open a new file using the editor, the indentation is already set to 4. Prettier does not require formatting code for it.
I hope this article has helped you configure ESLint, Prettier, and EditorConfig in your own projects. It took me a while to figure them out. For this type of configuration, I don’t think it’s best to get your code inspection and formatting experience by setting it up once and forgetting it. If you want to modify your configuration, you must remember to follow the pattern described above.