eslint、semistandard、standard 和 xo 都是用于 JavaScript 项目的代码质量保障工具,它们通过静态分析帮助开发者发现潜在错误、强制统一代码风格并提升可维护性。eslint 是一个高度可配置的插件化 lint 工具,而 semistandard、standard 和 xo 则是在 eslint 基础上封装的“零配置”或“低配置”方案,各自预设了不同的代码风格规则集。这些工具的核心目标一致,但在灵活性、默认规则、配置方式和扩展能力上存在显著差异,适合不同团队协作模式和技术偏好。
在现代前端工程中,代码一致性不仅是风格问题,更是可维护性和协作效率的关键。eslint、semistandard、standard 和 xo 都基于 ESLint 引擎,但设计理念迥异 —— 从完全自由到高度约束。本文从真实开发场景出发,深入剖析它们的技术差异。
eslint 提供完全开放的配置模型,所有规则均可开关或调整。
.eslintrc.js、.eslintrc.json 或 package.json 中的 eslintConfig 字段定义规则。eslint-plugin-react)和可共享配置(如 airbnb)。// .eslintrc.js 示例
module.exports = {
extends: ['eslint:recommended', 'plugin:react/recommended'],
rules: {
'no-console': 'warn',
'react/prop-types': 'off'
},
parserOptions: { ecmaVersion: 2022 }
};
standard 主张“无配置”,所有规则固化在包内。
# 安装后直接运行
npx standard
semistandard 是 standard 的变体,仅修改一条核心规则:允许分号。
standard 完全一致。# 使用方式与 standard 几乎相同
npx semistandard
xo 在“零配置”基础上提供有限扩展点。
xo 字段在 package.json 中微调。// package.json
{
"xo": {
"semicolon": false,
"rules": {
"no-await-in-loop": "off"
}
}
}
eslint: 默认不限制,需显式配置 semi 规则。standard: 禁止分号(semi: ["error", "never"])。semistandard: 要求分号(semi: ["error", "always"])。xo: 默认禁止分号,但可通过 semicolon: true 开启。// standard / xo (默认)
const a = 1
// semistandard / eslint (配置后)
const a = 1;
eslint: 默认不限制,常用 quotes: ["error", "single"]。standard/semistandard: 强制单引号。xo: 默认单引号,可通过 quoteProps 调整。// 所有工具默认行为
const msg = 'Hello'
// 双引号会报错(除字符串内容包含单引号外)
eslint: 默认不限制 var,但 eslint:recommended 不包含此规则。standard/semistandard: 禁止 var,强制 const/let。xo: 默认禁止 var(no-var: "error"),且要求 const 优先于 let。// 所有工具(除基础 eslint)均报错
var name = 'John'
// 正确写法
const name = 'John'
eslint 拥有最丰富的生态系统。
@typescript-eslint/parser)。// eslint + TypeScript 配置
module.exports = {
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
extends: ['plugin:@typescript-eslint/recommended']
};
standard/semistandard 仅支持原生 JavaScript。
xo 开箱支持现代语法。
typescript 依赖)。# xo 直接 lint .ts 文件
npx xo src/index.ts
eslint 本身不处理代码格式化,但可通过 eslint --fix 修复部分问题。
eslint-config-prettier 关闭冲突规则。// .eslintrc.js + Prettier
extends: [
'eslint:recommended',
'prettier' // 关闭 ESLint 中与 Prettier 冲突的规则
]
standard/semistandard 内置简单格式化能力(standard --fix)。
xo 深度集成 Prettier。
xo --fix 时自动调用 Prettier 格式化代码。# xo 自动格式化
npx xo --fix
eslint + @typescript-eslint + eslint-plugin-reacteslint 能提供细粒度控制,例如在 utils 目录禁用 React 规则。standard 或 semistandardxostandard 更严格。standard/semistandard 的局限性:无法处理非 JS 文件(如 .vue),在复杂项目中可能成为瓶颈。xo 的隐式依赖:使用 TypeScript 时需手动安装 typescript 包,否则解析失败。eslint 的学习曲线:新手易陷入配置地狱,建议从 eslint:recommended 逐步扩展。| 特性 | eslint | semistandard | standard | xo |
|---|---|---|---|---|
| 配置自由度 | 完全自由 | 无 | 无 | 有限(package.json 微调) |
| 分号要求 | 可配置 | 必须 | 禁止 | 默认禁止(可开启) |
| TypeScript 支持 | 需插件 | 不支持 | 不支持 | 内置 |
| Prettier 集成 | 需手动配置 | 无 | 无 | 开箱即用 |
| 适用场景 | 大型/复杂项目 | 喜欢分号的简洁项目 | 极简主义项目 | 现代前端项目 |
eslint 是唯一可持续的选择。standard 或 semistandard 能省去大量配置时间。xo 在零配置和严格性之间取得了最佳平衡。记住:工具只是手段,核心目标是减少团队在代码风格上的争论,把精力聚焦在业务逻辑上。
选择 eslint 如果你需要完全控制 lint 规则、支持多种框架(如 React、Vue、TypeScript)或需要与现有项目规范深度集成。它适合大型团队或对代码风格有严格定制需求的场景,但需要投入时间配置规则和维护 .eslintrc 文件。
选择 semistandard 如果你希望采用 StandardJS 的核心规则,但允许使用分号(;)结尾。它适合那些喜欢 StandardJS 简洁哲学,又不愿放弃分号以避免 ASI(自动分号插入)潜在问题的团队,提供比 standard 更宽松的语法约束。
选择 standard 如果你追求极致简洁、无需配置的开发体验,并接受其无分号、单引号、2 空格缩进等约定。它适合小型项目、开源库或快速原型开发,能立即统一团队代码风格,但牺牲了自定义规则的自由度。
选择 xo 如果你希望在零配置基础上获得现代 JavaScript 支持(如 ES2022+、TypeScript)、更严格的默认规则(如禁止 var、强制 const/let)以及开箱即用的 Prettier 集成。它适合追求前沿实践、重视代码健壮性的现代前端项目。
Website | Configure ESLint | Rules | Contribute to ESLint | Report Bugs | Code of Conduct | X | Discord | Mastodon | Bluesky
ESLint is a tool for identifying and reporting on patterns found in ECMAScript/JavaScript code. In many ways, it is similar to JSLint and JSHint with a few exceptions:
To use ESLint, you must have Node.js (^20.19.0, ^22.13.0, or >=24) installed and built with SSL support. (If you are using an official Node.js distribution, SSL is always built in.)
If you use ESLint's TypeScript type definitions, TypeScript 5.3 or later is required.
You can install and configure ESLint using this command:
npm init @eslint/config@latest
After that, you can run ESLint on any file or directory like this:
npx eslint yourfile.js
To use ESLint with pnpm, we recommend setting up a .npmrc file with at least the following settings:
auto-install-peers=true
node-linker=hoisted
This ensures that pnpm installs dependencies in a way that is more compatible with npm and is less likely to produce errors.
You can configure rules in your eslint.config.js files as in this example:
import { defineConfig } from "eslint/config";
export default defineConfig([
{
files: ["**/*.js", "**/*.cjs", "**/*.mjs"],
rules: {
"prefer-const": "warn",
"no-constant-binary-expression": "error",
},
},
]);
The names "prefer-const" and "no-constant-binary-expression" are the names of rules in ESLint. The first value is the error level of the rule and can be one of these values:
"off" or 0 - turn the rule off"warn" or 1 - turn the rule on as a warning (doesn't affect exit code)"error" or 2 - turn the rule on as an error (exit code will be 1)The three error levels allow you fine-grained control over how ESLint applies rules (for more configuration options and details, see the configuration docs).
The ESLint team provides ongoing support for the current version and six months of limited support for the previous version. Limited support includes critical bug fixes, security issues, and compatibility issues only.
ESLint offers commercial support for both current and previous versions through our partners, Tidelift and HeroDevs.
See Version Support for more details.
ESLint adheres to the OpenJS Foundation Code of Conduct.
Before filing an issue, please be sure to read the guidelines for what you're reporting:
Yes, ESLint natively supports parsing JSX syntax (this must be enabled in configuration). Please note that supporting JSX syntax is not the same as supporting React. React applies specific semantics to JSX syntax that ESLint doesn't recognize. We recommend using eslint-plugin-react if you are using React and want React semantics.
No, ESLint and Prettier have different jobs: ESLint is a linter (looking for problematic patterns) and Prettier is a code formatter. Using both tools is common, refer to Prettier's documentation to learn how to configure them to work well with each other.
ESLint has full support for ECMAScript 3, 5, and every year from 2015 up until the most recent stage 4 specification (the default). You can set your desired ECMAScript syntax and other settings (like global variables) through configuration.
ESLint's parser only officially supports the latest final ECMAScript standard. We will make changes to core rules in order to avoid crashes on stage 3 ECMAScript syntax proposals (as long as they are implemented using the correct experimental ESTree syntax). We may make changes to core rules to better work with language extensions (such as JSX, Flow, and TypeScript) on a case-by-case basis.
In other cases (including if rules need to warn on more or fewer cases due to new syntax, rather than just not crashing), we recommend you use other parsers and/or rule plugins. If you are using Babel, you can use @babel/eslint-parser and @babel/eslint-plugin to use any option available in Babel.
Once a language feature has been adopted into the ECMAScript standard (stage 4 according to the TC39 process), we will accept issues and pull requests related to the new feature, subject to our contributing guidelines. Until then, please use the appropriate parser and plugin(s) for your experimental feature.
ESLint updates the supported Node.js versions with each major release of ESLint. At that time, ESLint's supported Node.js versions are updated to be:
ESLint is also expected to work with Node.js versions released after the Node.js Current release.
Refer to the Quick Start Guide for the officially supported Node.js versions for a given ESLint release.
Open a discussion or stop by our Discord server.
Lock files like package-lock.json are helpful for deployed applications. They ensure that dependencies are consistent between environments and across deployments.
Packages like eslint that get published to the npm registry do not include lock files. npm install eslint as a user will respect version constraints in ESLint's package.json. ESLint and its dependencies will be included in the user's lock file if one exists, but ESLint's own lock file would not be used.
We intentionally don't lock dependency versions so that we have the latest compatible dependency versions in development and CI that our users get when installing ESLint in a project.
The Twilio blog has a deeper dive to learn more.
We have scheduled releases every two weeks on Friday or Saturday. You can follow a release issue for updates about the scheduling of any particular release.
ESLint takes security seriously. We work hard to ensure that ESLint is safe for everyone and that security issues are addressed quickly and responsibly. Read the full security policy.
ESLint follows semantic versioning. However, due to the nature of ESLint as a code quality tool, it's not always clear when a minor or major version bump occurs. To help clarify this for everyone, we've defined the following semantic versioning policy for ESLint:
eslint:recommended is updated and will result in strictly fewer linting errors (e.g., rule removals).eslint:recommended is updated and may result in new linting errors (e.g., rule additions, most rule option updates).According to our policy, any minor update may report more linting errors than the previous release (ex: from a bug fix). As such, we recommend using the tilde (~) in package.json e.g. "eslint": "~3.1.0" to guarantee the results of your builds.
Since ESLint is a CommonJS package, there are restrictions on which ESM-only packages can be used as dependencies.
Packages that are controlled by the ESLint team and have no external dependencies can be safely loaded synchronously using require(esm) and therefore used in any contexts.
For external packages, we don't use require(esm) because a package could add a top-level await and thus break ESLint. We can use an external ESM-only package only in case it is needed only in asynchronous code, in which case it can be loaded using dynamic import().
These policies don't apply to packages intended for our own usage only, such as eslint-config-eslint.
MIT License
Copyright OpenJS Foundation and other contributors, <www.openjsf.org>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
These folks keep the project moving and are resources for help.
The people who manage releases, review feature requests, and meet regularly to ensure ESLint is properly maintained.
![]() Nicholas C. Zakas |
![]() Francesco Trotta |
![]() Milos Djermanovic |
The people who review and implement new features.
![]() 唯然 |
![]() Nitin Kumar |
The people who review and fix bugs and help triage issues.
![]() fnx |
![]() Josh Goldberg ✨ |
![]() Sweta Tanwar |
![]() Tanuj Kanti |
![]() lumir |
Pixel998 |
Team members who focus specifically on eslint.org
![]() Amaresh S M |
![]() Harish |
![]() Percy Ma |
The following companies, organizations, and individuals support ESLint's ongoing maintenance and development. Become a Sponsor to get your logo on our READMEs and website.