How to Write a Custom ESLint Rule for Node.js
This article provides a practical, step-by-step guide to writing and
implementing custom ESLint rules for Node.js applications. You will
learn how ESLint uses Abstract Syntax Trees (ASTs) to analyze code, how
to structure a rule file using the meta and
create properties, and how to package your custom rule as a
local plugin to enforce your team’s specific coding standards.
Step 1: Understand the Structure of an ESLint Rule
ESLint rules are written in JavaScript and export an object with two
primary properties: meta and create.
meta: Contains metadata about the rule, such as its category, documentation, and the error messages it returns.create: A function that returns an object containing visitor methods. ESLint calls these methods as it traverses the Abstract Syntax Tree (AST) of your code.
Here is the basic boilerplate for a custom rule:
module.exports = {
meta: {
type: "suggestion", // "problem", "suggestion", or "layout"
docs: {
description: "Disallow the use of a specific variable name",
category: "Stylistic Issues",
recommended: false,
},
schema: [], // Defines configuration options if the rule accepts arguments
messages: {
avoidName: "Avoid naming variables 'temp'. Use descriptive names instead.",
},
},
create(context) {
return {
// AST selector methods go here
};
},
};Step 2: Identify the AST Nodes
ESLint parses your JavaScript code into an AST before analyzing it. To target specific code patterns, you must identify the corresponding AST node type. You can use online tools like AST Explorer (set the parser to “espree”) to paste your code and inspect the tree structure.
For example, if you write const temp = 1;, AST Explorer
reveals that the name temp is represented by an
Identifier node nested inside a
VariableDeclarator.
Step 3: Write the Rule Logic
Using the boilerplate, you can target VariableDeclarator
nodes to check if any variable is named “temp”. If a match is found, use
context.report() to trigger an ESLint warning or error.
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "Disallow naming variables 'temp'",
},
messages: {
noTemp: "Do not use 'temp' as a variable name.",
},
},
create(context) {
return {
VariableDeclarator(node) {
if (node.id && node.id.name === "temp") {
context.report({
node: node.id,
messageId: "noTemp",
});
}
},
};
},
};Step 4: Package the Rule as an ESLint Plugin
To use this rule in a Node.js project, you must expose it via an ESLint plugin.
- Create a directory named
eslint-plugin-customin your project’s root folder or as a separate local package. - Inside that directory, create an
index.jsfile. - Export your custom rule inside a
rulesobject:
const noTempRule = require("./rules/no-temp");
module.exports = {
rules: {
"no-temp": noTempRule,
},
};Step 5: Integrate the Plugin into Your Node.js Project
To load your local plugin, specify its path in your project’s
package.json dependencies, or link to it locally.
In your project’s .eslintrc.js config file, add your
plugin and configure the custom rule:
module.exports = {
plugins: [
// References 'eslint-plugin-custom' from your node_modules
"custom"
],
rules: {
// Enables your custom rule and sets it to trigger an error
"custom/no-temp": "error"
}
};When you run npx eslint ., ESLint will parse your files,
execute your custom rule logic against the codebase, and flag any
variable declarations named temp as errors.