felfel.dev

Setting up Prettier and ESlint for JS and React Apps

February 20, 2019 • ☕️ 7 min read

In any Frontend project, especially with big teams, it is important to standardize the code style and formatting, this has many benefits:

  1. It will ensure clean code which follows the best practices across the team, especially with interns or junior team members who might not know why a specific way of writing code if better than another.
  2. Will help everyone to learn and level up, as every linting rule is there for a purpose and each JS standard has the list of reasons with examples why any specific rule is needed.
  3. Reduces code review time and makes it more focused on code quality and optimizations instead of syntax and style, so you don’t have to add a comment again to ask your colleague to use const instead of var, or remove an unused variable or module.
  4. Will give you more confidence in your code, as you will be sure there will never be a production issue because someone had a typo in some variable name or be embarrassed by your console.log('LOL') slipping into production.

So, I hope I convinced you or gave you enough reasons to convince your team to adopt linting and styling tools for your project.

The most famous tools in the JS community for code formatting and syntax linting are Prettier and ESlint. We will see now how to get your project set up and ready to use these tools in three steps:

  1. Adding the required npm modules and configurations.
  2. Adding a pre-commit hook to make sure no code is pushed with linting errors.
  3. Handling legacy code that doesn’t follow linting rules and not autofixable.

Adding the required npm modules and configurations:

using npm:

> npm install --save-dev babel-eslint eslint eslint-config-airbnb eslint-config-prettier eslint-plugin-react eslint-plugin-import prettier pretty-quick

Or using yarn:

> yarn add -D babel-eslint eslint eslint-config-airbnb eslint-config-prettier eslint-plugin-react eslint-plugin-import prettier pretty-quick

Here we added eslint for code-quality rules and we will follow the Airbnb js/react standard for that.

Also, we added prettier which will format your code to follow a specific set of formatting rules.

Pretty-quick is used to apply prettier to the staged files only, we will use this for the pre-commit hook.

And the job of eslint-config-prettier is to turn off all ESLint rules that are unnecessary anymore or might conflict with Prettier rules. Now you would need to add some configuration files for your app to start following those rules.

Add a .prettierrc file:

{ 
 “printWidth”: 100,
 “trailingComma”: “all”,
 “tabWidth”: 2, 
 “semi”: true, 
 “singleQuote”: true
}

This is just an example if you want to change some default rules based on your or your team’s preference. You can do the same with eslint by adding .eslintrc

{
    "parser": "babel-eslint",
    "parserOptions": {
    "sourceType": "module",
    "allowImportExportEverywhere": false,
    "codeFrame": false
},
"extends": ["airbnb", "prettier"],
"env": {
    "browser": true,
    "jest": true
},
"rules": {
    "max-len": ["error", {"code": 100}],
    "prefer-promise-reject-errors": ["off"],
    "react/jsx-filename-extension": ["off"],
    "react/prop-types": ["warn"],
    "no-return-assign": ["off"]
  }
}

You notice there we are extending airbnb, and prettier to extend the default eslint rules with their rules for code quality and formatting. Also notice that we are using babel-eslint as the parser, which will allow eslint to lint all your valid babel (es6,7, …etc) code.

Adding Eslint to your code editor:

I will talk here about vscode, but I believe you can do the same with any code editor. First add a .editorconfig file in the root directory of your project, for example:

# http://editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
max_line_length = 100
trim_trailing_whitespace = true
[*.md]
max_line_length = 0
trim_trailing_whitespace = false
[{Makefile,**.mk}]
# Use tabs for indentation (Makefiles require tabs)
indent_style = tab
[*.scss]
indent_size = 2
indent_style = space

Then you can use the editorconfig vscode extension to override your editor’s default settings to follow the .editorconfig file.

Also, you can use the Prettier vscode extension to make prettier the default formatter for your js modules.

I also recommend you to enable onSave formatting and autofixing, you can do that by going to your vscode user settings Command + , or Code > Preferences > settings. Then add these two lines to your settings object:

“editor.formatOnSave”: true,
“eslint.autoFixOnSave”: true

Now your project has all the configurations and required to follow eslint and prettier.

2- Adding a pre-commit hook to make sure no code is pushed with linting errors.

You can easily add a pre-commit hook to your project using husky npm module, but there is another module that makes it even easier to lint your staged files before committing which is lint-staged.

npm install — save-dev lint-staged husky

Then add to your package.json file:

“husky”: {
    “hooks”: {
        “pre-commit”: “lint-staged”
    }
},
“lint-staged”: {
    “src/**/*.{js,jsx}: [“eslint”, “pretty-quick — staged”, “git add”]
},

This will run eslint and prettier on your staged files whenever you attempt to create a new commit. So all your new code now will be following the eslint quality and prettier formatting rules.

3- (Optional) Handling legacy code that doesn’t follow linting rules and not autofixable.

You mostly are all set by now, and you might not need this step. But if you have a large code base and it is being touched a lot by different team members then whenever anyone tries to edit a file, he will get linting errors for all the code in the file, as that will be the staged file now which will make it harder for others to refactor everything in every module they need to change.

There is a solution to that situation and we will do it on two steps:

First, we can use prettier to format all our code base to follow the prettier rules: You can solve this by first running prettier on all your codebase:

> prettier --write src/

Then do the same with eslint:

> eslint — fix src/

Run your code to make sure nothing is broken, which ideally it shouldn’t be.

Hint: You can always do git rebase --hard to reset your local branch and files to the latest commit, which is the status before you run the above commands. Just in case anything went wrong.

But even then, if you try to commit now, you will find the number of eslint errors is less but still (in a large code base) you might still be getting thousands of errors.

I fixed that by writing a small script that silences the broken rules only in the same file not globally over the whole codebase. And you can consider these as FIXMEs that you can clean up gradually at later point whenever you have time.

const fs = require('fs');
const { SourceCode, CLIEngine } = require('eslint');

const cli = new CLIEngine();
const reports = cli.executeOnFiles(['src/**/*.js']);
reports.results.forEach(fileReport => {
  const { filePath } = fileReport;
  const codeString = fs.readFileSync(filePath).toString();
  const codeLines = SourceCode.splitLines(codeString);

  fileReport.messages.forEach(lintingMessage => {
    const disableMsg = `/* eslint ${lintingMessage.ruleId}:0 */`;
    // ignore if the the rule was already there
    if (codeLines.includes(disableMsg)) return;
    codeLines.splice(0, 0, disableMsg);
  });
  fs.writeFile(filePath, codeLines.join('\n'), err => err && console.log(err));
});

After running the above script on your codebase, you will end up with files like this:

/* eslint no-shadow:0 */
/* eslint react/require-default-props:0 */
/* eslint max-len:0 */
/* eslint react/destructuring-assignment:0 */
/* eslint jsx-a11y/label-has-for:0 */
// the module's code
...

Note: there is a downside of using the above technique which is your git history will be missed up now, you can’t git blame correctly now because all the code was sorta re-written!


I have used the above techniques in a large codebase in my company, and it helped a lot with reducing the code review comments related to minor linting issues, increased the overall quality and shape of the code, and overtime all the developers started to fix the eslint ignores and the code is getting cleaner with every release. I hope you try it and reap similar benefits.