ESLint — A Proofreader for your Code

A practical guide to setting up and using ESLint

By Michael Chang

September 29th, 2020

image

My Journey

I constantly ask myself, how do I maintain a high quality codebase? Well, the obvious answer is simple — to maintain a good coding standard. What’s not so simple, however, is what should be part of this standard and how I enforce this standard.

I didn’t have a good answer. I tried my best to come up with my own standard, and I tried to enforce this standard in code reviews. But it wasn’t enough. My “standard” was constantly changing and things kept on slipping past code reviews. This all changed when I learned about ESLint.

ESLint

ESLint is Javascript’s linter. It works by analyzing your code and warning you if any configured rules are violated. These rules can detect suspicious or concerning coding quality or formatting issues. It’s similar to Google Doc’s or Microsoft Word’s spelling and grammar checking — essentially an automatic proofreader for your code! This is exactly what I needed. I can create a coding standard from ESLint’s vast collection of rules and have ESLint enforce them.

So it turns out, I was already using ESLint — just not in a way that was effective. Create React App ships with a native ESLint configuration but is extremely basic. I needed to update this configuration so that my automatic proofreader could make me a better developer.

Setup

To start, ESLint provides a handy setup tool. Run npx eslint --init, and you will be asked a series of questions that will help ESLint create your initial setup.

How would you like to use ESLint? To check syntax only, To check syntax and find problems, or to check syntax, find problems, and enforce code style.

I recommend selecting check syntax, find problems, and enforce code style to get the most out of ESLint.

What type of modules does your project use? JavaScript modules (import/export), CommonJS (require/exports), or none of these. Which framework does your project use? React, Vue.js, or none of these. Does your project use TypeScript? Yes or no. Where does your code run? Browser, Node, or both.

These would depend on your codebase.

How would you like to define a style for your project? Use a popular style guide, or answer questions about your style, or inspect your JavaScript file(s).

I recommend using a popular style guide. This will allow you to take advantage of a style guide that took experts thousands of hours to build. And you get it for free!

Which style guide do you want to follow? Airbnb, Standard, or Google.

I highly recommend using Airbnb. From what I’ve seen, it’s the most popular style guide and I consider it the de facto standard in the Javascript community.

What format do you want your config file to be in? JavaScript, YAML or JSON.

This is up to you but remember — we’re Javascript developers!

Once the questionnaire is done, ESLint will install all the necessary dependencies and create your base configuration in .eslintrc.js.

Configuration

Now that we have a base configuration, let’s understand what it does. The three main parts are rules, plugins, and extensions.

Rules

Rules, defined in the rules section of the configuration, determine what the ESLint proofreader looks for in your code. ESLint provides hundreds of these rules that help maintain code quality. These rules can either be set to off, warn or error. off will do nothing, warn will log the error, and error will log the error and return a 1 exit code so integrations such as continuous integrations will fail.

module.exports = {
  rules: {
    'no-underscore-dangle': 'off',
    'no-console': 'warn',
    'no-empty': 'error',
  },
}

Some rules also allow you to customize a rule with addition configuration options so you don’t have to turn the entire rule off.

module.exports = {
  rules: {
    'no-empty': ['error', { allowEmptyCatch: true }],
  },
}

Plugins

But there are a lot more rules than that. ESLint also provides plugins, defined in the plugins section of the configuration, to allow third-parties to develop rules themselves. Most established frameworks such as React, Jest, and Testing Library, take advantage of this and expand upon ESLint’s native rules. In fact, I usually evaluate a framework’s maturity by checking whether they have their own ESLint rules!

module.exports = {
  plugins: ['react'],
  rules: {
    'react/no-deprecated': 'error',
  },
};

Extensions

All told, there are easily thousands of ESLint rules. How could you possibly decide which rules to enable without spending weeks and weeks to understand them all? You don’t — extensions, defined in the extends section of the configuration, handle that for you. Extensions such as Airbnb’s ESLint Configuration, something that the ESLint setup tool provides if you selected Airbnb’s style guide, have enabled hundreds of rules; rules that will also be enabled for you if you use their extension.

Here are a few notable ESLint configurations from common Javascript frameworks:

Overriding + Disabling

A side effect of using extensions is that you may not like all of their rules. Fortunately, you can customize or turn off these rules in the rules section.

module.exports = {
  extends: ['airbnb', 'plugin:react/recommended'],
  rules: {
    'no-empty': ['error', { allowEmptyCatch: true }],
    'react/jsx-filename-extension': [
      'error',
      { extensions: ['.js', '.jsx'] }
    ],
  },
};

Even if you like a rule, sometimes you encounter a situation where you want to temporarily disable it. You can accomplish this using comments.

  • /_ eslint-disable _/: Disables ESLint for all lines below

  • /_ eslint-disable-line _/: Disables ESLint for the current line

  • /_ eslint-disable-next-line _/: Disables ESLint for the next line

You can also specify (comma separated) rules after the disable comment to specifically disable those rules instead of disabling all.

import React from 'react';
import PropTypes from 'prop-types';

*/* eslint-disable */*
import ReactDom from 'react-dom';
*/* eslint-enable */*

*/* eslint-disable-line arrow-body-style */* const App = () => {
  return <h1>ESLint Demo</h1>;
};
App.propTypes = {
  */* eslint-disable-next-line react/no-unused-prop-types, react-redux/no-unused-prop-types */*
  unused: PropTypes.string.isRequired,
};

export default App;

Of course, if you find yourself disabling the same rule over and over again, you may want to consider permanently disabling it.

Running

Now that we have the desired configuration, it’s finally time to run ESLint. To do this, add the following to your package.json.

{
  "scripts": {
    "lint": "eslint . ",
    "lint:fix": "eslint . --fix",
  },
}

npm run lint will run ESLint and any errors and warnings will be printed to the console. Fix and repeat. npm run lint:fix will run ESLint as well but will also try and automatically fix any violated rules. Any rules that can’t be automatically fixed will be printed to the console.

Final Thoughts

Now, you should be up and running with ESLint. The next step is to fix any violations— I had to deal with over 30,000 errors myself! But I consider this well worth it in the long run. ESLint monitors and guides me to create and maintain a high quality codebase so I don’t have to obsess over the little details. Instead, I can focus that obsession into creating a better product.

Resources



Continue Learning