Get Started with ESLint v1.0

You've compared the various JavaScript linting options and decided to use ESLint on your project. This post won't cover the concept of linting or benefits of ESLint, but will help you get started with it by showing how to install, configure, understand, and extend ESLint. If you would like a more general overview and introduction, I recently gave a short (< 5 minute) Intro to ESLint Lighting Talk at a local JavaScript meetup.

eslint --version

Update July 31, 2015: ESLint version 1.0.0 has been released and this post has been updated

The current version as of the time of this writing is 0.24.1, but there is an upcoming 1.0.0 version which is in release candidate phase (currently 1.0.0-rc-3). In order to be future-proof and avoid dealing with breaking changes right away, we're going to be using the new version.


Installing

From within your project directory:

npm install eslint --save-dev  

If you are upgrading from a previous version, npm will not automatically update ESLint to a new major release (as there are breaking changes), so you will need to use the latest tag or specify 1.0.0 directly:

npm install eslint@latest --save-dev  
# or
npm install eslint@1.0.0 --save-dev  

You will now have a local installation of ESLint. You can also install globally by using a -g flag like so:

npm install eslint -g  

Configuring

ESLint is a very powerful and flexible tool, and because of this it can be a little intimidating to set up. Fortunately, it comes with a built in initialization wizard which will generate a basic configuration for you based on your answers to some questions. Let's see how that works.

eslint --init

If you installed ESLint globally, cd into your project directory and simply run:

eslint --init  

If you only have a local installation, you'll need to use:

./node_modules/.bin/eslint --init

You will then be presented with a question whether you use tabs or spaces.

eslint --init first question

Make your selection and proceed with the next questions. Below are the questions it will ask and my example responses.

eslint --init results

Next let's take a look at what was created for us.

Config File

After running through the initializer, an .eslintrc configuration file is generated with three main objects, "rules", "env", and "extends":

{
    "rules": {
        "indent": [
            2,
            "tab"
        ],
        "quotes": [
            2,
            "single"
        ],
        "linebreak-style": [
            2,
            "unix"
        ],
        "semi": [
            2,
            "always"
        ]
    },
    "env": {
        "es6": true,
        "node": true
    },
    "extends": "eslint:recommended"
}

Rules

The general theory behind rules in ESLint is that they can be individually added and configured. A big change in ESLint version 1.0 is that there will no longer be any rules enabled by default. This means that unless you specify a rule explicitly (or extend from a shared config, which we will get to later), ESLint will essentially do nothing when you run it.

To add a rule, first add its name to the "rules" object in your config file. You can find a complete list of rules at http://eslint.org/docs/rules/.

You will then need to set the error level of the rule and any other options which apply to the rule. The error level can be one of three values:

  • 0 - Turn the rule off
  • 1 - Turn the rule on as a warning
  • 2 - Turn the rule on as an error

The difference between an error and a warning is the exit code that eslint will have when it finishes. If any errors are found, eslint will exit with a 1 exit code, otherwise it will exit with a 0, even if warnings are thrown. If you are linting within a build step (you are, right?), this allows you to control which rules should "break your build" and which ones you might just want to know about.

Each rule may also have its own unique options, apart from the error level. For example, in the config I generated above, indent has the "tab" option set, and semi is set to "always". You can learn what all of the options are for a particular rule by visiting its page in the documentation.

These are the basics of rules. For more details on other topics including turning on rules from within files using configuration comments, disabling rules for specific lines, and more, see http://eslint.org/docs/user-guide/configuring#configuring-rules.

Environments

The code you are writing may be designed to be used within a particular environment which expects certain global variables to be present, for example document in browsers and it in Mocha. By setting the environment id to true in the "env" section of .eslintrc, you are telling ESLint not to freak out when you use those global variables without defining them first.

The es6 environment, on the other hand, is a little different. This tells ESLint's AST parser (Espree) that you are going to be using ES6/ES2015 features. Espree can parse all valid ES6 syntax, but this is disabled by default. You need to either turn on individual language features, or enable the es6 environment which turns them all on for you (except for modules, which you will still need to manually set if you're using ES6 modules).

The final section of our generated .eslintrc file is "extends". Now let's see what that does for us.

Sharable Configurations

Prior to 1.0, ESLint had a default set of rules which would be applied unless you explicitly turned them off. This caused some confusion for new users, and frustration for others who wanted more control. Therefore, the decision was made to get rid of the default rules and create a set of "recommended" rules which could be opted-into. These recommended rules are all aimed at preventing bugs, and do not include style rules. The line "extends": "eslint:recommended" in our config file is how we opt-in to these recommended rules.

This touches on an even larger and more powerful feature of ESLint, which is that anyone can create a configuration and share it with others. These so-called "sharable configurations" typically begin with the prefix eslint-config-, such as the popular eslint-config-standard. These configurations can be pulled into your project using "extends", and then you can override rules or environments as necessary. For more details on how to create, distribute, and use sharable configurations, see http://eslint.org/docs/developer-guide/shareable-configs


Linting

Now you're all set up with a configuration and you're ready to cross your fingers, lint your files, and hope you don't have hundreds or thousands of errors.

ESLint has a powerful command line interface (CLI), and the general format is eslint [options] [file|dir]*.

You can take a look at all of the options at http://eslint.org/docs/user-guide/command-line-interface#options, but all that's really necessary is:

eslint file.js      # Lints a single file  
eslint dir/         # Lints a directory  

The output will be grouped by file, and will specify the line:column number, severity (warning/error), reason for the error, and the name of the rule for each failure. A contrived example is shown below.

eslint results

Now it's up to you to fix your code, or change the rules. :)

Nibbling through the errors

On large, established projects it's possible to have hundreds or thousands of errors the first time linting is applied. It can be difficult to tell from the default output of ESLint whether this means your code is very inconsistent and full of errors, or whether a few rules or options do not align with your project's conventions. And even if all the rules are set up properly, going through and fixing the errors can be a major chore.

To solve these problems, I created eslint-nibble, which runs in a two step process. First, an overall summary of the rules is presented, giving a feel for any rules which may possibly be misconfigured or a bad fit for you.

eslint-nibble stats

Then if you give it the name of a rule, it will display only the errors from that particular rule, including a snippet of your code to show where the problem is for each error.

I find it easier to focus on making one type of change at a time. It also makes the whole process feel more manageable, since you can declare small victories by cleaning up an entire rule, rather than just getting the errors down to 283 from 304. Hopefully you'll find this useful as well.

Summary

You now have the knowledge and tools to start using ESLint on your projects. In this post, we installed the 1.0 version of ESLint, used the built-in initialization wizard to create a configuration file, explored the parts of the file and ways to customize it, performed linting with the CLI, and got an overview of a tool designed to make it easier to chew through linting errors.

Now go out there and get the fuzz off of your JavaScript!


Extra Credit

Here are a few advanced topics and links which you may wish to investigate further.

Custom Rules

You aren't limited to the (ever-expanding) set of rules within the ESLint core project, you can write your own.

Plugins

Projects like angular and react have their own plugins (eslint-plugin-angular and eslint-plugin-react) which package up a set of custom rules designed for their coding style.

Integrations

There are plugins for popular text editors like Sublime Text, Atom, and vim which will perform linting in real time while you edit. There are also integrations with build system such as Grunt and Gulp

Ignoring Files

Sometimes you don't want to lint certain files or directories.

Custom Parsers

If you are using ES2016/ES7 code like async and await, you can do so if you use the babel-eslint parser instead of the default Espree parser. Other third-party parsers exist as well.