Although this article is not about the basics of ESLint, I will take a moment to show you how to get started. First of all install ESLint globally. Make sure you have Node.js on your machine and run the following command from the terminal:
That’s it, ESLint is installed. Now go to any folder you want to work from and create a file called
.eslintrc. Put the following configuration in there:
lint-me.js in the same folder and put the following code in it:
Now run ESLint using the following command:
You should see one error saying: “‘shout’ is defined but never used”. ESLint’s recommended rules check for most common mistakes. Of course creating a function but never using it is a waste! Try to fix it by adding:
shout('Wecodetheweb is awesome');. Now run ESLint again, it will give no errors anymore. That’s it!
When you are just starting out, start by extending the recommended rules like we just did. Why? Because you will get lost in all the possible rules if you try to select your own set.
If the config file is empty, no rules will be applied. Only syntax errors will make ESLint error. If you extend a set of rules, all rules you define yourself will override those from the set.
The recommended rules catch the most common errors and bad practices in your code. Things like unknown variables being used, unreachable code or duplicate keys on objects will make ESLint error. Stuff that no developer wants! All rules that have a checkmark listed here are included in the recommended set.
Most people start using linters because they want all their team members to use the same style, like single quotes or two spaces of indentation. Although that is certainly useful and you should probably do that, in this article we’ll focus on improving actual code quality. Let’s start by reducing ‘cyclomatic complexity’.
Cyclomatic complexity is measured by the amount of branches a piece of code (in our case, a single function) has. A branch is a single and unique route you can take trough a piece code. High complexity is bad because it makes code hard to understand and maintain, as a result it is easy for bugs slip though.
Consider the following example:
This function has a cyclomatic complexity of 2, because there are two possible routes the execution can take. Two is a nice and low complexity level. Let’s configure ESLint to keep it that way. 👍
The first value ‘2’ means this rule should trigger an error. The default value for complexity is 20 (!) which is way too high. Therefore we pass it the value 5. Now when a function has a higher complexity than five, it will trigger an error.
Somewhere between 4 and 6 is a nice value for complexity. Just try it out, take a complex piece of code from your existing codebase and run it through ESLint with this complexity setting, happy refactoring! 😎
Functions should be short and concise. This makes them easy to read, maintain and reduces bugs.
The above function has 4 statements (which is fine 😇). More statements means more lines of code, make sure this is true by configuring the max statements per line rule. We want to keep our functions small like this. Let’s configure ESLint to check this for us:
Somewhere around 7 is a nice value for max statements, you could go even lower. Max statements per line should be one, this makes statements easy to detect.
Remember callback hell? 🔥
Don’t do this! You can extract the parts into functions or use something like Promises to prevent this. But let’s make sure this does not happen anymore using two more rules:
This will make sure we never nest blocks and callbacks more then two levels deep, saving us from complex, hard to read and debug, tree-like code. 🎄
These were some important rules that can help you write better code. But this is just the tip of the iceberg. Some of my favorite rules are:
"eqeqeq": 2- Makes sure you never use
!=to check equality, because you know, it couses trouble.
"no-eval": 2- We all know using eval is a generally bad idea…
"no-var": 2, "prefer-const": 2- When using ES2015 or above (which you should if you can). This rule encourages you to never use
var‘s and use
const‘s instead of
let‘s where possible, this forces you to think twice before reassigning a variable and not use the inferior function scoped
"max-lines": [2, 90]- Limits the maximum lines per file. It’s not that important what the exact value is, just makes sure you don’t get those 200+ line monsters.
"no-return-assign": 2, "no-param-reassign": 2, "array-callback-return": 2- Can save you from those nasty ‘assignments that should be comparisons’ bugs inside functional array methods.
For rules that you don’t want or need to set the value from you can just set the error level:
"rule": 2. Otherwise you need to pass an array with the value as the second item:
"rule": [2, 'value']. What type of value it has differs per rule and is documented on the ESLint website.
We came up with a pretty decent configuration already! Check it out:
I can imagine you don’t want to check out all the rules that ESLint has to offer for yourself, but just want a ‘good’ config. There are some pre-defined configs out there that you can use. I also created one called eslint-config-ngerritsen. You can use it as follows:
I got you covered selecting a pretty strict ruleset. It also has the rules for ES2016 and above. Ofcourse you are free to override any rule by defining your own rules afterwards or creating your own config using this one as a base. Other well know configs are eslint-config-google, eslint-config-airbnb and eslint-config-standard.
Note that just having an ESLint config in place will have no advantage of no one ever runs it. Make sure it runs automatically when you commit or push code using a pre-commit hook or a CI tool like Travis.
- ESLint official website: eslint.org
- eslint-config-ngerritsen: https://www.npmjs.com/package/eslint-config-ngerritsen