ESLint: the rule engine that keeps a JavaScript codebase honest

Summary

A rule engine rather than a style opinion: every check in ESLint can be switched off, retuned or promoted to a build breaker, extensions cover the framework specific corners, and the same configuration runs in the editor and in the pipeline. Free, open source, and the closest thing this ecosystem has to an enforceable shared standard.

Recommend
Name
ESLint
Version
10.11
Pricing
Free
Open source
Open source
Operating system
Node.js编辑器扩展
Updated
2026-10-08 20:51

The traffic light for a codebase

Every team that grows past a handful of contributors runs into the same slow decay. One file ends a statement with a semicolon, the next does not. Someone leaves an unused variable behind, another shadows a name that was already taken three scopes up, and an asynchronous call goes out without anyone catching its failure. None of this breaks the build today. All of it costs somebody an afternoon six months from now. Review cannot catch that class of problem, because it appears in every single commit.

The tool is unglamorous by design. It reads source files one statement at a time and compares them against a list of rules. Each rule owns exactly one shape: an unused binding, a promise nobody receives, a comparison that is always true, a branch that can never run. On a match it reports the position, the rule name and a severity. The severity is the column teams underestimate. Rules are not equal in weight, and a report in which everything shouts equally loudly is worth about as much as no report.

screenshot

Rules live in configuration, not in taste

What separates this tool from the checkers that came before it is that almost nothing is hard coded. Any rule can be switched off, lowered to a warning or raised to an error, and each one accepts its own options. A team that dislikes a particular writing habit turns it off and moves on with the work. A team that has been burned by one specific defect pattern raises the matching rule to an error and never argues about it again.

The extension model follows the same reasoning. Problems specific to a framework stay in their own packages instead of being pushed into the core: one set for type aware checks, one for components, further sets per framework or per test library. A project installs only what it needs, and the configuration stays short because every line in it refers to a rule that is actually running.

Two surfaces consume the same rule set. In the editor, violations appear while typing, underlined with the rule name on hover, which turns most corrections from a review comment into a few seconds of work. In the pipeline, the same configuration walks the whole repository and stops the build when an error appears. The editor catches mistakes while the author still holds the context in mind. The pipeline catches what a tired human let through.

screenshot

What changed in this generation

The configuration format was rebuilt from the ground up. The old cascade of inherited files, with its chains of extensions and its scope implied by directory, has been replaced by a flat array in which every entry declares exactly which files it applies to. The result is easier to reason about, easier to debug and faster to load, at the price of a one time migration that most projects have already finished.

Automatic repair widened at the same time. A large share of the rules can rewrite the offending code instead of only describing it, and the rewrites stay conservative so that a repair pass does not quietly change behaviour. Formatting, the least interesting topic in any review, largely disappears once repair runs on save and once more before the commit.

A rule set is worth exactly what the agreement behind it is worth. The tool guarantees one thing only: once the agreement is made, it still holds after everyone who negotiated it has moved to another project.

Governance counts for infrastructure this dull. The project sits under an open foundation, releases on a predictable rhythm and keeps a published policy for breaking changes, which is why a large repository can take a major version without freezing feature work for a quarter.

Where it pays off, and where it cannot

For one person, a well maintained community configuration removes a whole class of defects before the first commit. For a team the value is different in kind. A style guide written in a wiki is respected as long as nothing is urgent. The same guide expressed as rules runs on every push, for every contributor, including the one who joined last week.

The boundary deserves the same care. This compares shapes in the syntax; it is not a type checker and it is not a test suite. It will not tell you that a function returns the wrong shape at runtime, and it will not tell you that a feature is broken. It also will not make a design better. A repository with three hundred rules and no tests is still a repository with no tests.

A modest order beats a complete list. Start from the configuration the community already maintains, let it report only for a week and look at what actually fires. Raise the rules that caught real problems, silence the ones that produced nothing but noise, and review the rest at a regular interval. A rule everyone has learned to ignore is worse than no rule at all, because it trains the team to ignore the report.

ESLintDownload
Supported systems: Node.js 编辑器扩展