Intro
What is ESLint? ESLint is a static code verification tool that automatically reports an error/ warning if the set rules are broken.
Why would you want to use this? It allows developers to automatically enforce the company's code style guide and standards, prevents common errors and reduces time spent on PRs leaving a comment that someone forgot to add ";" at the end of the line. Ultimately increasing the quality of your codebase and increasing each developer's efficiency.
Common ESLint setting to enforce Javascript best practices
To start with, probably the easiest and most powerful rule to get a lot out of ESLint is to add an extension called "eslint:recommended" and if you are using typescript the also "plugin:@typescript-eslint/recommended". Additionally, on top of it, I would suggest taking a look at these rules:
"no-console": This rule helps identify and remove any remaining console.log statements, ensuring that debug logs are not present in production code.
"no-unused-vars": It detects unused variables and parameters, helping to identify and remove unnecessary code and improve code maintainability.
"no-undef": This rule checks for undeclared variables and helps catch typos or potential issues with variable scoping.
"strict": The "strict" mode enforces stricter coding standards by requiring variables to be declared with var, let, or const and prevents the use of undeclared variables.
"no-magic-numbers": This rule discourages the use of "magic numbers" in code by requiring the use of named constants or variables, which improves code readability and maintainability.
"consistent-return": It enforces consistent return values in functions, ensuring that all code paths return a value or explicitly use "void" for TypeScript functions.
"no-else-return": This rule discourages the use of unnecessary "else" statements when the "if" statement already has a return or throw statement, improving code clarity and reducing cognitive load.
"no-use-before-define": It prevents the use of variables before they are defined, avoiding potential bugs caused by hoisting and helping maintain clean code structure.
"prefer-const": This rule encourages the use of const for variables that are not reassigned, promoting immutability and reducing the risk of accidental variable mutations.
"eqeqeq": This rule enforces the use of strict equality (===) over loose equality (==), promoting safer and more predictable comparisons by requiring the comparison of both value and type.
"complexity": This rule helps identify overly complex functions by setting a threshold for cyclomatic complexity, allowing you to maintain more readable and maintainable code by encouraging smaller, more focused functions.
In code it would look like this:
{
"root": true,
"env": { "node": true, "browser": true, "es2021": true },
"extends": [ "eslint:recommended", "plugin:@typescript-eslint/recommended" ],
"parserOptions": { "ecmaVersion": 2021, "sourceType": "module" },
"plugins": [ "@typescript-eslint" ],
"rules": {
"no-console": "error",
"no-unused-vars": "erroe",
"no-undef": "error",
"strict": ["error", "global"],
"no-magic-numbers": ["warn", { "ignore": [0, 1], "ignoreArrayIndexes": true }],
"consistent-return": "error",
"no-else-return": "error",
"no-use-before-define": "error",
"prefer-const": "error",
"no-restricted-syntax": ["error", "WithStatement"],
"eqeqeq": "error",
"complexity": ["warn", 10] }
}
Integrate ESLint with other linting tools and frameworks
"Prettier": Integrating ESLint with Prettier so that they wouldn't conflict each other- https://www.npmjs.com/package/eslint-config-prettier.
"Typescript": Typescript and ESLint can work together and report issues in the compiler, grab the eslint-typescript plugin and get working together and catch the potential bugs as you write your code- https://www.npmjs.com/package/@typescript-eslint/eslint-plugin
this plugin can do more of just that, I highly recommend checking out the official documentation here- https://typescript-eslint.io/.
"3rd party predefined rule plugins": these plugins allow you to fast-track some of the setup and align your code standards with some of the already established communities that have gone through rigorous processes of setting these rules in. the firts place.
Google- https://www.npmjs.com/package/eslint-config-google
AirBnB- https://www.npmjs.com/package/eslint-config-airbnb and for typescript https://www.npmjs.com/package/eslint-config-airbnb-typescript
Vue- https://www.npmjs.com/package/eslint-plugin-vue
Angular- https://www.npmjs.com/package/@angular-eslint/eslint-plugin
React- https://www.npmjs.com/package/eslint-plugin-react
Next.js- https://www.npmjs.com/package/eslint-config-next
The only ESLint code editor plugin you will ever need:
ESLint plugin by Microsoft- automatically underlines the code that has an eslint error- https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint
ESLint and PRs (local and/or pipeline check)
What's the use of ESLint if only you are using it? ESlint rule enforcement should be a part of your DevOps process, it is highly recommended that you run your eslint . (this command runs it on all of your codebase) either
in your pipeline or
locally pre-commit f.x. using Husky. If you are going for the local environment option and your codebase is relatively large you might want to upgrade your ESLint call to run only on the files that you have changed by doing this- eslint --fix $(git diff --name-only develop '*/.js' | xargs) For more discussion on this see this stackOverflow post https://stackoverflow.com/questions/54511168/enable-eslint-only-for-edited-files
Custom ESLint rules
If you cannot find an ESLint rule that fits your requirements it is possible to create one yourself! For example, if for some reason you would want to disallow using the word "coconut" in your code base you could write a custom rule that will throw you an error if someone tried to do that. That would look something like this:
// avoid-name.js
module.exports = {
meta: {
messages: {
avoidName: "Avoid using variables named '{{ name }}'"
}
},
create(context) {
return {
Identifier(node) {
if (node.name === "coconut") {
context.report({
node,
messageId: "avoidName",
data: {
name: "coconut",
}
});
}
}
};
}
};
// someFile.js
var coconut = 2;
// ^ error: Avoid using variables named 'coconut'
// avoid-name.test.js
var rule = require("../../../lib/rules/avoid-name");
var RuleTester = require("eslint").RuleTester;
var ruleTester = new RuleTester();
ruleTester.run("avoid-name", rule, {
valid: ["apple", "banana"],
invalid: [
{
code: "coconut",
errors: [
{
messageId: "avoidName"
}
]
}
]
});
Conclusion
In conclusion, ESLint is a powerful tool for static code verification that offers numerous benefits for developers and codebases. By enforcing code style guides and standards, ESLint helps maintain consistency across the development team and improves the overall quality of the codebase. It detects common errors, such as unused variables and undeclared variables, reducing the likelihood of bugs and improving code maintainability. Additionally, ESLint promotes best practices, such as avoiding magic numbers, using strict equality, and reducing code complexity. Integrating ESLint with other tools and frameworks, such as Prettier and TypeScript, enhances its functionality and allows for a seamless development experience. By incorporating ESLint into the DevOps process and running it in pipelines or locally, you can ensure rule enforcement throughout the development lifecycle. Lastly, ESLint provides the flexibility to create custom rules, enabling you to tailor the tool to your specific requirements. Overall, ESLint is a valuable asset for developers, increasing code quality, reducing errors, and enhancing productivity.
What is you favourite ESLint rule? Let me know in the comment section
Top comments (1)
Isn't it sad that one of the rules prevents you from writing Clean Code as advised by Robert C. Martin in the book by the same name?
Weird enough, there's only 1 complaint on github of eslint.
I'm confused - is clean code's top-to-bottom not such a big of a deal / or is it that no frontend developer gave it a shot / read it?