The Nodesource Blog

#shoptalk Subscribe

Streamline JavaScript Development with ESLint

JavaScript is a dynamic language which, at runtime, executes common programming behaviors that static programming languages perform during compilation. This makes JavaScript a productive language but at the cost of not having a safety net to validate the code.

This problem is easily addressed with a structured approach to writing your code: linting.

What is Linting?

Linting is the process of running a program that will analyze code for potential errors.

The name is derived from a particular program named lint that flagged some suspicious and non-portable constructs (likely to be bugs) in C language source. The term is now applied generically to tools that flag suspicious usage in software written in any computer language. -- Lint (software), Wikipedia

Why is Linting Important?

  • It defines best practices for projects and teams
  • It makes communication easier
  • It establishes coding rules that remove troubling bugs and performance regressions
  • It provides needed safety nets

A quick example of linting:

var num = parseInt("071"); // 57
var num = parseInt("071", 10); // 71

Linting rules can be established to catch errors, like in the example above where the radix is not explicitly defined.

How Do I Lint My Code?

There are a multitude of projects within the JavaScript community that have attempted to solve linting - JSCS, JSHint, and ESLint are just a few of the all-time major ones.

ESLint has established itself as the clear winner because of the architectural decisions behind it. Nicholas C. Zakas didn't want to force a particular set of rules on developers, he wanted a system where everyone could choose what's right for them. As a result, ESLint is a plugin based system that allows you to pick and choose, and add any desired rules. The power of ESLint comes from the use of an AST (Abstract Syntax Tree) to provide "hooks" into plugins to analyze the code.

But I'm Using JSCS or JSHint Already!

Luckily, there's a quick and easy fix - the polyjuice package is here to help! Polyjuice allows porting of JSCS or JSHint linting rules to ESLint with a quick command that help up and running with ESLint quickly.

npm install -g polyjuice
polyjuice --jscs .jscsrc.json > .eslintrc.json

An important note is that polyjuice works with JSON configuration files - so if a project is using a JavaScript or YAML JSCS file, it needs to be converted it into a JSON configuration file.

How to Get Started with ESLint

ESLint is flexible in how it allows specification of rules. The most common practice is to create a .eslintrc.* file in the base of a project. Another option is to define an eslintConfig object inside of the project's package.json but, I advise against this technique. Using the eslintConfig object can limit discoverability of ESLint usage, unnecessarily pollutes the package.json file, and breaks the standard in most projects of using the dedicated file.

The easiest way to get started is to start from an existing configuration like the Airbnb JavaScript Style Guide, the Google JavaScript Style Guide, or StandardJS.

Here's a list of some of the most popular ESLint configs:

  • eslint-config-airbnb-base
  • eslint-config-google
  • eslint-config-standard
  • eslint-config-idiomatic
  • eslint-config-jquery
  • eslint-config-node-style-guide
  • eslint-config-wordpress

It's easy to get up and running with one by npm installing it in a project, replacing eslint-config-airbnb-base with the style guide of choice and the --save-dev flag to ensure it's _only used in development installs.

npm install eslint-config-airbnb-base --save-dev

All ESLint configurations follow a standard naming convention (eslint-conf-*) which allows us to shorten the name when using it with the extends property.

With this in mind, once the chosen ESLint config has been npm installed, a project's .eslintrc.json should be updated to include it:

{
    "extends": "airbnb-base"
}

See the configuring guide on the ESLint site for more options.

Start Using ESLint

The eslint package can be installed globally (via npm i -g eslint) or locally (via npm install --save-dev eslint). In general, I avoid installing globally as much as possible and rely on a package or project's devDependencies to resolve execution.

If ESLint has been included in a project's devDependencies, simple and automated linting commands can be added to the npm scripts in the project's package.json:

{
 "scripts" : {
    "lint": "eslint **/*.js",
    "lint-html": "eslint **/*.js -f html -o ./reports/lint-results.html",
    "lint-fix": "eslint --fix **/*.js"
 }
}

Note: If you want a primer on how to use npm effectively, you should take a look at our article, 11 npm Tricks to Knock Your Wombat Socks Off!

The First Lint

After the package.json has some linting scrips defined, use them! The first linting npm script defined above can be run with:

npm run lint

This will generate a command line report of errors and what file and line number they occurred.

Getting Better Output from Linting

With the previously defined linting scripts, the lint-html script will generate a HTML report.

npm run lint-html

Personally, I find the html report more valuable because of the links it provides to the documentation. An example of this is no-delete-var, which explains the no-delete-var rule in further detail than the command line output would spit out. It includes a code example, along with links to the rule source code for further (technical) understanding.

Automating Code Style Fixes

Another great feature is the automatic code fixing. On the rules page individual rules that have a wrench can be automatically fixed.

npm run lint-fix

That command is defined in the package.json above. This script will automatically use the automatic code fixing feautre of ESLint, and clean up a lot of code style issues according to the project's config.

Setting Linting Rules

In the above example, the airbnb-base ESLint config was used - which is a great start. That said, there are some rules that may or may not work for any given project - luckily, ESLint allows all rules from a config to be overridden according to the .eslintrc.json file.

{
  "extends": "airbnb-base",

  "rules": {
    "no-console": "off",
    "prefer-arrow-callback": "off"
  }
}

Sometimes, though, the defined set of rules don't apply to everything and you need to override on a case by case basis. This can be done inline within the JavaScript files.

Examples of Inline Rules:

Ignore warnings about global variables named var1 and var2.

/* global var1, var2 */

Disabling for a block of code:

/* eslint-disable */
eval(str);
/* eslint-enable */

Switching from expecting double quotes to single quotes:

/* eslint quotes: ["error", "single"] */

var str = 'he said "I love node.js"'; // Uses single quotes - error free!

var str = "he said 'I love node.js'"; // Uses double quotes - throws an error!

Use Plugins for Specific Needs

ESLint has a vibrant set of plugins from the community. Like the ESLint configs, they follow a standard naming convention: eslint-plugin-*.

For example, React introduces a new syntax and can easily be linted with a use of an ESLint plugin. The React plugin can be installed to devDependencies with a simple command:

npm install --save-dev eslint-plugin-react

Once installed, this new syntax and set of rules can be included in the ESLint config by adding the react plugin to the project's .eslintrc.json file:

{
  "extends": "standard",
  "plugins": ["react"]
}

Get ESLint Integrated Into Your Workflow

ESLint has tons of integrations with text editors, build systems, CLI tools, and even source control hooks. The wide variety of integrations can be explored, for any particular use case, at the integrations user guide on the official ESLint site.

Go Further with ESLint

If you want to use ESLint even more, there is an awesome-eslint list, which has a nice variety of different ESLint configs, parsers, plugins, tools, and tutorials.

What's the Next Step?

Once you're up and linting, defining a style guide and a list of best practices takes time. It is advisable to start within your comfort zone and expand from there. JavaScript has a lot of amazing features but it doesn't mean we have to use every single one to write quality code. Chose the rules and plugins that provide quick wins. Have discussions within your team on pain points and iterate.