Rob O'Leary Rob is a solution architect, fullstack developer, technical writer, and educator. He is an active participant in non-profit organizations supporting the underprivileged and promoting equality. He is travel-obsessed (one bug he cannot fix). You can find him at roboleary.net.

Automate formatting and fixing JavaScript code with Prettier and ESLint

6 min read 1707

Automate formatting and fixing JavaScript code with Prettier and ESLint

Linting and pretty-printing your JavaScript code can help you catch errors early, make your code more legible, and improve code quality. However, when you use a formatter (for pretty-printing) and a linter side by side, there can be some friction. For example, the formatter can do something that the linter deems a problem. The linter can overwrite style changes from the formatter. They can pull in different directions.

To use them together successfully, you need to get them on the same page. In this article, I will discuss how you can use the most popular formatter, Prettier, with the most popular linter, ESLint. I will show you how to set them up and use them together on the command-line, and in Visual Studio Code (VS Code) to automatically fix and format your code.

I have seen different methods for tackling how to use them together, but some are hacky solutions because of limitations in code editors. I will discuss the merits and demerits of some of these. You can make your own mind up on what is best.

First, let’s get a broad overview of linting rules so we can understand what the demarcation between a linter and formatter should be.

Rules of linting

There are two broad categories of linting rules:

  1. Formatting rules: These rules affect the style of the code. These rules are not concerned with bugs. For example, the rule ‘no-mixed-spaces-and-tabs’ rule in ESLint ensures that only tabs or spaces are used for indentation. Prettier has a ‘tabs’ option for the same thing.
  2. Code-quality rules: These rules improve code quality and are likely to prevent or catch bugs. For example, the rule ‘no-implicit-globals’ in ESLint disallows global scope variables. Name collisions can occur with global variables created from other scripts. This usually leads to runtime errors or unexpected behavior.
Prettier's formatting rules and ESLint's code-quality rules overlap on linting rules Venn diagram
Venn diagram of linting rules.

The problem is that the rules of Prettier and ESLint overlap. We would prefer that they don’t!

Generally, we want Prettier to handle the first category and ESLint to handle the second. There are rules that may be difficult to categorize as one or the other. We don’t need to get pedantic about which category they fit into. Our interest is in ensuring that either Prettier or ESLint perform a particular action and do not bump into one another.

Separation between Prettier's formatting rules and ESLint's code-quality rules
Rule demarcation between Prettier and ESLint.

As for the order to run them in, it is best to run Prettier before ESLInt. Prettier formats documents by reprinting the entire program from scratch in a consistent way to eliminate any possibility of formatting mistakes. So, if you want to let ESLint in on the formatting act, you should run it after Prettier to prevent the changes from being overwritten.

If you’re not familiar with ESLint and Prettier, let’s cover how do the initial configuration of them in the next section. If you are familiar, you can skip ahead to the Methods section.

Initial configuration for ESLint and Prettier

Both ESLint and Prettier are available to download from npm and Yarn. For every project, you will want to create a package.json and add them as devDependencies.

We made a custom demo for .
No really. Click here to check it out.

npm install --save-dev eslint
npm install --save-dev --save-exact prettier

ESLint starts as a blank slate. It won’t do anything until you create a configuration with some rules. Put your configuration file (.eslintrc.{js,yml,json}) into your project directory and you’ll be ready to lint. You can set up a global configuration, but ESLint has deprecated it (discourages it). I still use a global configuration. 🤫

With a configuration in place, you can run ESLint from the command-line as below. You can read ESLint’s Getting Started Guide for more details.

Running ESLint in code
Using ESLint on the command-line.

On the other hand, Prettier has a default configuration. It can be run without creating your own configuration file, so you can begin using it straight away. The recommendation is to use a specific version of Prettier on big projects, otherwise updates may cause changes to many files and add noise to your git commits. You should probably use a .prettierignore file to ignore things that should not be formatted also. You can read Prettier’s installation guide for more information.

Inserting Prettier code
Using Prettier on the command-line.

A typical package.json will look something like what I have below. I target the files in the folders src and test for my npm scripts. I prefer to skip .eslintignore and .prettierignore files if possible — simpler is preferable! 😅

{
  "name": "basic-project",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "lint": "npx eslint src test",
    "lint:fix": "npm run lint -- --fix",
    "prettier": "npx prettier src test --check",
    "prettier:fix": "npm run prettier -- --write",
  },
  "author": "rob o'leary",
  "license": "ISC",
  "devDependencies": {
    "eslint": "^7.25.0",
    "prettier": "^2.2.1"
  }
}

All the major code editors have extensions for ESLint and Prettier. For VS Code, the official extensions are Prettier – Code formatter and ESLint.

Inserting ESLint in VS Code
Using ESLint in VS Code.

Various methods for linting and pretty-printing your code

I would recommend the first method below. It is the cleanest and most efficient.

1. Remove conflicting rules and run serially

It’s easy to turn off rules that conflict with Prettier in ESLint by using the following configs:

First, install the config. This is just for JavaScript:

$ npm install --save-dev eslint-config-prettier

Then, append that config name to the extends array in your local .stylelintrc.* ESLint config file. Make sure to put the prettier config last so it will override settings from other configs.

Example .eslintrc.json:

{
  // ...
  extends: [
    // ...
    'eslint:recommended',
    "prettier" // Make sure this is the last
  ],
  // ...
}

Now, you are free to run Prettier and ESLint together without any side effects.

You can run prettier and ESLint one after another like you would do on the command line by defining them as npm scripts. Here is how that looks in a package.json:

{
   "name": "no-worries-setup",   
   "version": "1.0.0",
   "scripts": {
    "lint": "npx eslint src test",
    "lint:fix": "npm run lint -- --fix",
    "prettier": "npx prettier src test --check",
    "prettier:fix": "npm run prettier -- --write",
    "format": "npm run prettier:fix && npm run lint:fix",
  }
  // ...
}

Now, you can run the npm run format command to format and fix all your code in one go.

Configuration in VS Code

  1. Install the extensions: ESLint, Prettier, and Format Code Action.
  2. Update your user settings (settings.json), as below:
    {
      //...
      "editor.defaultFormatter": "esbenp.prettier-vscode",
      "eslint.probe": [
          "javascript",
          "javascriptreact",
          "vue"
      ],
      "editor.formatOnSave": false,
      // Runs Prettier, then ESLint
      "editor.codeActionsOnSave": [
        "source.formatDocument",
        "source.fixAll.eslint"
      ],
      "vetur.validation.template": false
      // ...
    }

First, you need to disable the editor formatting on save (editor.formatOnSave). We want to handle everything through code actions.

In March 2020 (v1.44), the editor.codeActionsOnSave property was updated to accept an array of code actions, which permits ordered code actions. If we install the Format Code Action extension, we can make formatting available as a code action. So now, we can run Prettier and ESLint as code actions in whichever order we like. Sweet!

In this example, we run Prettier first with the action source.formatDocument (it uses the default formatter), and then we run eslint --fix with the source.fixAll.eslint action.

The slint.probe property is used to target the languages that ESLint should validate. You can use eslint.validate if you want to see pop-up messages instead.

If you use the Vetur extension, ensure it does not do its own validation. There is a setting vetur.validation.template, which you should not enable.

2. Run Prettier followed by ESLint programmatically

The following applications offer a unified way to run prettier followed immediately by eslint --fix on files:

First, install the package. This is just for JavaScript:

$ npm install --save-dev prettier-eslint

Next, you need to write your own implementation to target your files and run the formatting.

Below is a basic example of formatting a string:

const format = require("prettier-eslint");

// notice, no semicolon in the original text
const sourceCode = "const {foo} = bar";

const options = {
  text: sourceCode,
  eslintConfig: {
    parserOptions: {
      ecmaVersion: 7,
    },
    rules: {
      semi: ["error", "never"],
    },
  },
  prettierOptions: {
    bracketSpacing: true,
  },
  fallbackPrettierOptions: {
    singleQuote: false,
  },
};

const formatted = format(options);

// notice no semicolon in the formatted text
formatted; // const { foo } = bar

Obviously, this method requires more work to target the files, read the content, and write the output.

Configuration in VS Code

You can install and use the Prettier ESLint extension. You can read the README for instructions.

3. Run Prettier as if it is an ESLint rule

This is generally not recommended because:

  1. You get formatting issues reported as problems by ESLint. Do you want squiggly red lines for things that Prettier will fix automatically for you anyway?
  2. It is a bit slower than running Prettier directly.
  3. You have another layer where bugs can be introduced.

You can use ESLint plugins that let you run Prettier as if it was a linter rule:

First, install the plugin. This is just for JavaScript:

$ npm install --save-dev eslint-plugin-prettier

Then, append the plugin(s) to the plugins array in your .stylelintrc.* file.

Example .eslintrc.json:

{
  "plugins": ["prettier"],
  "rules": {
    "prettier/prettier": "error"
  }
}

Wes Bos recommended this method a couple years ago. It was a reasonable option at the time, but there are more options available now.

Configuration in VS Code

  1. Install the extensions: ESLint and Prettier.
  2. Update your user settings (settings.json) as below:
    "eslint.alwaysShowStatus": true,
    "editor.formatOnSave": true,
    // turn it off for JS and JSX, we will do this via eslint
    "[javascript, javascriptreact]": {
      "editor.formatOnSave": false
    },
    // tell the ESLint plugin to run on save
    "editor.codeActionsOnSave": {
      "source.fixAll": true
    },
    // Optional BUT IMPORTANT: If you have the prettier extension enabled for other languages like CSS and HTML, turn it off for JS since we are doing it through ESLint already
    "prettier.disableLanguages": ["javascript", "javascriptreact"],
    

Conclusion

Prettier and ESLint can be used together very effectively. It requires some configuration, but that should be straightforward after reading this article! I love having this setup. It’s great to have some tasks taken off your hands and reclaim some headspace. It will help you to improve your code quality and give you a more legible codebase without manual intervention.

: Debug JavaScript errors easier by understanding the context

Debugging code is always a tedious task. But the more you understand your errors the easier it is to fix them.

LogRocket allows you to understand these errors in new and unique ways. Our frontend monitoring solution tracks user engagement with your JavaScript frontends to give you the ability to find out exactly what the user did that led to an error.

LogRocket records console logs, page load times, stacktraces, slow network requests/responses with headers + bodies, browser metadata, and custom logs. Understanding the impact of your JavaScript code will never be easier!

.
Rob O'Leary Rob is a solution architect, fullstack developer, technical writer, and educator. He is an active participant in non-profit organizations supporting the underprivileged and promoting equality. He is travel-obsessed (one bug he cannot fix). You can find him at roboleary.net.

Leave a Reply