Using eslint to its fullest -- and introducing 🛠️lint-fix-nodemon!
Tags: javascript, productivity, node, vue
Published: 2020-03-15 20:37:31

There are lots of articles about why you should be using eslint (and prettier if you're into that) to lint your JavaScript code, so I'm not going to waste your time trying to convince you of that. Instead I'm here to tell you, don't just use them...

> **DEEPLY INTEGRATE THESE TOOLS INTO YOUR CODEBASE**
> _make it easier to use the linter than not_

Whether you're building a single page app, an API, or a library to publish on NPM, doing this will save you and your collaborators tons of time and effort. So what do I mean specifically?

- **Auto "fix" every time you save** - 
  trust me, this is magic and gives you superpowers
- **Don't rely on IDE plugins to do your linting** - 
  add the tools into your repo and dev workflow directly
- **Use git hooks to enforce rules before code gets committed** -
  don't let the infractions build up

If you're already on board and just want some tooling recommendations, just skip down [to the bottom](#showme) :) Otherwise, let me briefly explain why.

### Run eslint "fix" every time you save

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/0z7a1izqkocj6n05xe4x.gif)

I recently started working in a codebase that doesn't use semicolons. While I prefer (and am used to) using them and we can argue about it for an hour, the truth is it doesn't really matter these days. But I'm going to keep typing them because my fingers are in charge. But while I'm coding, if I realize I typed one, then have to go back and remove it, it's just a complete waste of time if I could let a robot do it for me. With auto-fix enabled, when I save, they just disappear.

I once had a coworker who refused to use the tooling I had set up (and insisted on using vim but was bad at it). I'd be helping him debug something, and watching him code. Everything would take an extra 20% longer, because I'd watch him write some code, then spot trivial formatting errors, and go back to fix them one by one.

**BUT IT'S CHANGING THINGS?!** That is the point. Learn to work with it and use it to your advantage. When I want to move a block of code into an adjacent if statement, I just move one bracket, hit save, and all the indentation is now magically fixed. Multiply each of those tasks times a few seconds and I've just saved a huge amount of time every day, not to mention the mental energy of thinking about these decisions. This is especially important when working on a project with many people who may have different habits.

Occasionally you may run into problems with one auto-fixing rule conflicting with another, like preferring short arrow functions vs keeping lines shorter than 100 characters. I'm not going to lie, it can be annoying, and sometimes I've had to add an eslint ignore, or write a statement a different way. But you fine-tune your rules, and you get used to it. The balance of time/effort saved is well worth the occasional hazard.


### IDE plugins vs integrated tools in your repo

An IDE plugin can be great if you want to highlight linting errors in your code directly. But relying on the plugin to fix on save or keep the code clean for your team is a recipe for not everyone playing by the rules. Not everyone uses the same editor. Not everyone has the same plugins or plugin  settings enabled. **Build it into the repo and make it easier to use the linter than not.**

### Use git hooks to enforce your rules

I've seen countless codebases that have an eslintrc file, but the rules are not actually followed. If you're going to have linting rules, you should enforce them. The easiest way to make sure that is the case is to not let people commit/push code until they follow the rules. Yes it can be annoying, but by always following the rules, you avoid letting the linting errors/warnings build up to the point that they are overwhelming, which makes them less useful. You can always skip the checks during a crisis or set up your rules to be more relaxed for certain scenarios.

On a related note - also add a linting check in your CI tools!

# Great - just show me how already <a name="showme">

What tools to use really depend on what kind of project you are working on, but here are a few quick suggestions. I'll add more resources here as I find new great tools.

-----------------------

### Git hooks
[Husky](https://github.com/typicode/husky) is an awesome tool that adds configurable git hooks to your repo. It has a ton of options, and is super easy to use. After installing as a dev dependency, you define hooks in your package.json file.
```json

  "scripts": {
    "lint": "eslint ./",
    ...
  },
  "husky": {
    "hooks": {
      "pre-commit": "NODE_ENV=production npm run lint",
      "pre-push": "npm run test"
    }
  },
 ...
```

-----------------------

### Enabling lint+fix in a webpack project
Use [eslint-loader](https://github.com/webpack-contrib/eslint-loader) to add eslint into your (dev) webpack build process. After installing as a devDependency, you need to add the following to the module.rules section your development config:

```javascript
{ // enable eslint + fix
  enforce: 'pre', // runs on the original file
  test: /\.(js|vue)$/, // adjust for your project
  loader: 'eslint-loader',
  exclude: /node_modules/,
  options: {
    emitWarning: true, // false to show errors in browser overlay
    fix: true, // enable fixing!
  },
}
```

-----------------------

### Enabling lint+fix in a vue-cli project
Vue cli just uses webpack under the hood, but abstracts away the webpack config. Use [@vue/cli-plugin-eslint](https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint) to add eslint-loader into your build process. Install using the vue-cli with `vue add eslint`. Lint on save is enabled by default.

-----------------------

### Enabling lint+fix in a backend / api project
This is why I wrote this article - to share a new tool I've released :)
**Say hello to [lint-fix-nodemon](https://github.com/theoephraim/lint-fix-nodemon)!**

Confused? Already using eslint with [nodemon](https://github.com/remy/nodemon)? It's not too hard, but here are the problems I encountered with all the different setups I tried:
- **Double restarts** - nodemon detects a first change when you save the file, and then again after eslint fixes it. Restarting twice may not be a huge deal, but anything that slows you down that happens 100 times a day adds up quickly.
- **ESLint failures can get stuck** - in certain circumstances (like starting up your `npm run dev` script at the beginning of a coding session) if eslint fails, it can fail the process so it doesn't start watching your files. Why should things work differently the first time I run it? If you have a lot of errors to fix, this can be a big pain...

This tool (which I've been using as an unpublished script for a long time) fixes both of these issues. It watches your files, runs eslint on change, and only restarts nodemon AFTER fixes have been applied. Also if anything fails on the first run, no problem - it will keep watching and try again when you save.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/atatbqyc4lj7bpvv4h7r.png)

So after installing (`npm i lint-fix-nodemon --save-dev`), configure things in your package.json file. I usually add script called "dev" to start the tool. By default nodemon will run the "main" script (or you can pass one to the script), and it will respect the "nodemonConfig" settings it finds. By default it will ignore "node_modules" and any files/folders that start with ".". The same files that are "watched" will be linted.

Here is an example:
```json
{
  "scripts": {
    "dev": "lint-fix-nodemon api/start.js",
    ...
  },
  "nodemonConfig": {
    watch: ["api/"],
    ignore: ["api/scripts"]
  },
  ...
}
```

-----------------------

### So what's next?

- I could probably add a lot more options to this library. Please open issues if you run into problems!
- I use a similar script to run the linter (with fixes) and then run my tests (using jest) on each save. Hello TDD! I'll probably release something more generalized soon, maybe a tool called `lint-fix-and` :)
- I still have been wanting to spend some time to set up automated linting   to auto fix the css/less/sass and pug in my vue single file components.


I hope this article and [lint-fix-nodemon](https://github.com/theoephraim/lint-fix-nodemon) are helpful for a few folks. Please let me know if you have any other suggestions to add, or are stuck on something.

Cheers!