Lint That Javascript

February 07, 2018

The Coding Histories Vol III: The Trials of Mt. Ecma

Mt. Etna

Mt. Etna Ecma, probably

Gather around children, and I’ll tell you a tale. Once not so long ago, there was a traveler on a path to coding glory. This traveler was skilled in the mysteries of “Java,” which helped her in battle against the enemy: hordes of nefarious bugs. For Java had a compiler to catch issues before runtime and a series of IDEs that would flag mistake such as unused imports and variable declarations that might slow the traveler down or trip her up.

But one day the traveler set foot on Mt. Ecma, where Java was forbidden. Only Javascript was allowed to be practiced on its nearly lawless slopes, and most of its disciples chose to use lighter editors. The traveler tried many times to reach the summit, but each time she stumbled in a different way and slid back to the bottom. When she had almost given in to despair, a wise elder from the Temple of “Airbnb” offered a way to bring discipline to her climb. What follows is what the traveler learned about the power of LINTING.


Intro

What is linting?

Linting is running a program that will analyze code for potential programmatic and stylistic errors. Javascript applications in particular can benefit from running a linter because the language does not have a static type system or a compiler to catch some common mistakes. A Javascript linter can be configured to catch all kinds of things. Just to name a few, a linter could push you to:

  • Use const for all of your references; avoid using var. Why? This ensures that you can’t reassign your references, which can lead to bugs and difficult to comprehend code.
  • Use object destructuring when accessing and using multiple properties of an object. Why? Destructuring saves you from creating temporary references for those properties.
  • Consistently use the same style of quotes—either single or double—across the entire application. Why? Enforcing one or the other can make your code easier to read and prevents arguments about preferred style.
  • Follow accessibility best practices such as adding a role and tabindex to non-semantic html elements.

How is linting handled?

Linting can be done from the command line, as a text editor plugin, as part of a bundler such as Webpack, or even as part of a build pipeline. For new applications, it’s easy to run a linter from the beginning and write new code to satisfy the prescribed rules. For existing codebases, it is often easier to lint files bit by bit as they are touched. In these cases, some linters can even automatically fix certain warnings across the entire project.


Workshop: Set it up for your application and editor

Setup

Workshop time. For linting purposes today, go ahead and grab an existing work repository. We’ll be using ESLint.

If you want to include eslint as part of a build system, then install it locally with npm install eslint --save-dev. (You can also just install it globally).

With that done, run ./node_modules/.bin/eslint --init. We'll be choosing Use a popular style guide and then Airbnb. Next answer whether you're using React. Finally, select json as your config file format. Some extra dependencies will now download, and you'll see a shiny new .eslintrc.json in your file tree. That config file will have exactly one thing in it: {"extends":"airbnb"}.

Configuration

Congratulations, you can now run your linter from the command line with ./node_modules/.bin/eslint . (which you should probably add as a script to your package.json). If you're running the command on an existing project for the first time, it will probably return many, many warnings and errors. That's okay! While ESLint and Airbnb's style guide are great, the tools are mostly likely enforcing some rules that your team disagrees with, or they are trying to parse some files that the linter doesn't understand. To solve it, we'll add some configuration options to our .eslintrc.json.

Rules

Let's start by overriding some rules that the Airbnb preset defines. In my project, we don't use semicolons to end statements, but the linter is throwing an error every time that happens. To fix it, we'll add a rules section to the config and specify "semi": [2, "never"], where "semi" is the name of the rule, 2 represents a warning level of "error", and "never" says to throw that error if a semicolon is ever added. Instead of just turning off the rule, I have flipped it on its head and said "no semicolons in this application!". Take that Airbnb ❤️!

There are three warning levels: "off" or 0 turn a rule off, "on" or 1 turn a rule on as a warning, and "error" or 2 turn the rule on and returns an exit code of 1 if it fails. See more, here.

I just significantly reduced my reported error rate with this one rule, and my config file looks like this:

{
  "extends": [
    "airbnb"
  ],
  "rules": {
    "semi": [
      2,
      "never"
    ]
  }
}

Evaluate some of the rules that you're failing and maybe go and tweak the settings!

Env / Plugins

You may also see some errors like 'it' is not defined, 'Feature' is not defined, or 'window' is not defined. These are because Eslint does not understand that those variables are only available from their Javascript runtimes (Jest, CodeceptJS, and the browser, respectively). We need to let ESLint know in our configuration file which environments we are using. Jest and the browser can be added out of the box with:

  "env": {
    "browser": true,
    "jest": true
  }

But if you try to add in "codeceptjs/codeceptjs": true, it gives back an error:

Error: /Users/localadmin/workspace/eslint_practice/.eslintrc.json:
	Environment key "codeceptjs/codeceptjs" is unknown

CodeceptJS offers the aptly named eslint-plugin-codeceptjs, which should be npm installed as a dev dependency and then specified in the plugins section of the .eslintrc.json. After all of that, my config file looks like this:

{
  "plugins": [
    "codeceptjs"
  ],
  "extends": [
    "airbnb"
  ],
  "env": {
    "browser": true,
    "jest": true,
    "codeceptjs/codeceptjs": true
  },
  "rules": {
    "semi": [
      2,
      "never"
    ]
  }
}

Ignoring Files

There might be some files that you don't want parsed. node_modules are ignored by default, but I also don't want my compiled code in my dist directory of my coverage report being analyzed. You can add a .eslintignore file and specify files and directories just like a .gitignore.

Automatic Fix

ESLint offers the ability to automatically fix some syntax errors. Running your eslint command with --fix at the end of it can help standardize your code with less manual effort on your part. Just make sure everything still builds and runs properly afterward if you run it on a large existing project!

Editor Integrations

One great part of ESLint is the editor integrations available for it. On my team, we use the VSCode ESLint Plugin, which shows us our warnings and errors in realtime as we edit files. A plugin is also available for Jetbrains editors like Intellij and Webstorm. A full list of integrations is available on ESLint's site.


Tl;dr

Setting up linting rules for your Javascript application helps maintain high code quality standards. You should do it. ESLint is a good choice that has many editor integrations and can also be run as part of a Webpack build. If you don’t want to write an entire custom set of rules, the Airbnb Preset is a great starting point. You can override any rules you disagree with.