ESLint 和 Prettier 打架?前端工程师的代码格式化终极指南
去年我接手一个遗留项目,打开代码文件就傻眼了——同一个文件里,缩进有2个空格、4个空格,甚至还有Tab。分号时有时无,引号单双混用。更崩溃的是,CI构建时ESLint报错300多个,Prettier格式化后又冒出200多个。
这不是段子。据2023年State of JS调查,78%的前端开发者同时使用ESLint和Prettier,但其中35%的人遇到过两者冲突。说白了,两个工具都想管你的代码,但规则不一样。
它们到底在争什么?
ESLint是代码质量警察。它抓的是逻辑错误:未使用的变量、全局污染、console.log没删干净。它的规则更像“代码规范”——比如强制使用===代替==,禁止eval。
Prettier是代码排版强迫症。它只管格式:缩进几个空格、行宽多少、括号要不要换行。它不在乎你的变量有没有被使用,只在乎看起来整不整齐。
问题来了:ESLint也能管格式。比如max-len限制行宽,indent控制缩进。Prettier也管这些。两套规则撞在一起,就像两个交警同时指挥一个路口。
典型的冲突场景:ESLint说函数参数必须换行,Prettier说一行能放下就别换。你该听谁的?
最佳实践:让Prettier管格式,ESLint管质量
这不是我拍脑袋想的。ESLint官方文档明确建议:用Prettier处理格式问题,ESLint专注于代码质量。具体怎么做?
第一步:关掉ESLint里所有和格式相关的规则。
安装eslint-config-prettier,它会自动禁用ESLint中与Prettier冲突的规则。2023年这个包在npm上每周下载量超过500万次,说明这是主流做法。
npm install --save-dev eslint-config-prettier
然后在.eslintrc里加上:
{
"extends": ["some-other-config-you-use", "prettier"]
}
注意:prettier必须放在extends数组的最后一位,这样它才能覆盖前面的格式规则。
第二步:用Prettier作为唯一的格式化工具。
在项目根目录建一个.prettierrc文件,统一团队的格式偏好。我的团队常用配置:
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 100
}
关键:这个文件必须所有人保持一致。据GitHub上一项统计,因Prettier配置不一致导致的PR冲突,占团队协作问题的12%。
第三步:用eslint-plugin-prettier把Prettier集成到ESLint里。
这个插件会把Prettier当成ESLint的一条规则来运行。格式不对,ESLint直接报错。好处是:你只需要运行ESLint,就能同时检查质量和格式。
安装:
npm install --save-dev eslint-plugin-prettier
配置:
{
"plugins": ["prettier"],
"rules": {
"prettier/prettier": "error"
}
}
但这里有个坑:eslint-plugin-prettier在大型项目中可能拖慢速度。Prettier官方建议在编辑器里用Prettier插件实时格式化,CI里只跑ESLint。我自己更倾向于后者——编辑器里Prettier自动修正,CI里ESLint只检查逻辑问题。
实战中的三个教训
教训一:不要用eslint –fix格式化代码。
很多人习惯eslint --fix一键修复。但如果你同时用了Prettier,这个命令可能会产生二次格式化——先修逻辑,再修格式,两次操作结果可能不一致。正确的做法是:先prettier --write格式化,再eslint检查质量。
教训二:团队配置要版本控制。
.prettierrc和.eslintrc必须提交到Git仓库。我见过一个团队,有人本地装了Prettier VS Code插件但没配项目文件,结果MR里的代码格式五花八门。后来加了.editorconfig文件统一编辑器行为,才算解决。
教训三:新项目直接用标准配置。
别从零开始写规则。ESLint推荐eslint:recommended,Prettier用默认配置。等你遇到具体问题再微调。据JetBrains 2023开发者调查,60%的前端团队使用标准配置,只有10%的团队自定义超过10条规则。
一个完整的示例工作流
假设你用React + TypeScript:
-
安装依赖:
npm install --save-dev eslint prettier eslint-config-prettier eslint-plugin-prettier @typescript-eslint/parser @typescript-eslint/eslint-plugin -
.eslintrc.json配置:
{ "parser": "@typescript-eslint/parser", "extends": [ "eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier" ], "plugins": ["@typescript-eslint"], "rules": { "no-unused-vars": "warn", "@typescript-eslint/no-explicit-any": "warn" } } -
.prettierrc配置:
{ "semi": true, "singleQuote": true } -
package.json添加脚本:
{ "scripts": { "format": "prettier --write .", "lint": "eslint . --ext .ts,.tsx", "check": "npm run format && npm run lint" } }
这样,团队里任何人运行npm run check,都会先格式化再检查质量。
一点个人看法
ESLint和Prettier的冲突,本质上是代码质量工具职责划分不清晰的问题。Prettier的出现其实是好事——它把格式这件事从ESLint里剥离出来,让每个工具专注做一件事。
但工具只是工具。我见过团队把Prettier配置调了30多行,就为了括号要不要换行这种细节。说实话,这种争论浪费的时间,比格式不一致带来的麻烦多得多。
用默认配置,跑通流程,把时间花在真正的代码逻辑上。这才是这两个工具存在的意义。