Create your own ESLint Plugin with custom project-specific Linting Rules (5 min)

Linting rules are a powerful tool to establish common ground within a development team. The rules define guidelines on how to format and structure your code.

Using predefined rule sets, like Airbnb’s ESLint config with more than 2 million weekly downloads, is really popular nowadays. Some frontend frameworks even include them by default.

But the real power of ESLint lies in custom rules! Most grown projects have these fragile parts within an application that Junior developers are afraid to touch. You have to do things in a certain way and you always have to watch out not to do anything wrong.

My recommendation to all Seniors: Don’t write tech documentation nobody is going to read! Simply create custom ESLint rules to provide guidelines to your colleagues and catch common mistakes early.

That’s exactly what I’m going to show you here. We’re going to create our very own ESLint plugin with project-specific rules.

Example Use Case

For making sure our Jest tests run properly, my team has to make sure to always wait for React-Testing-Library’s “waitFor” to resolve.

That’s why we want ESLint to throw an error if it spots the usage of “waitFor” without a preceding “await” expression.

// 😒 waitFor(() => {}))
// 🤩 await waitFor(() => {})

1. Setup a new package for your plugin

Create the following file structure:

eslint-plugin-abc
|__ index.js
|__ package.json

Add this basic package definition to your package.json:

Add the actual ESLint rules to your index.js. You will find more explanations right after the code section.

How does it work?

We added a new custom rule no-waitfor-without-await. If activated, our rule will be applied to all nodes (= code blocks) matching our selector. In our case, that’s every expression named waitFor, without a preceding await expression.

Under the hood, ESLint is using AST for targeting specific code blocks like function declarations, module definitions, and expressions. It kind of works like CSS. With a selector string, you can target elements and their children with certain attributes and states.

If you need help finding the proper selectors for your own plugin, check out ASTExplorer. Simply past the code snippet you want to target and explore your AST nodes. I also recommend reading the official ESLint docs on how to combine various selectors and filter for certain attributes.

For reference, I added a condition for calling context.report(). By doing so, you can make your selectors even more specific. You will have access to the node object with lots of additional information about the current code block. This information can then be used to either invoke a warning/error or moving on without.

2. Add your package to your client application

Simply install your new plugin package in your client application (e.g. React, Vue project):

npm install ./packages/eslint-plugin-abc

Or

yarn add ./packages/eslint-plugin-abc

For making things easy, I’m not using any package registry here. Feel free to use other means of including your plugin in your main package.

3. Activate your linting rules in .eslintrc

The last thing you have to do now is to add your new plugin and its rule to .eslintrc in your client application root. If you don’t see this file yet, simply create it:

module.exports = {
...
rules: {
...
'abc/no-waitfor-without-await': 'warn'
},
plugins: ['abc']
}

You have to add the plugin to your plugins list AND register the rule with your plugin’s name as a prefix (abc). Instead of emitting a warning, you can of course also decide to use “error”.

Now try it! Simply start your linter like you always do. For using IDE integration, you might have to restart your IDE.

Conclusion

Creating your own ESLint rules will make onboarding new team members easier and faster. Every developer gets instant feedback and common project-specific mistakes will be automatically found.

Frontend Engineer

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store