别再手动调格式了!5款代码格式化工具深度对比,效率提升10倍

第一次用Prettier,没仔细看配置,好家伙,一跑直接把整个项目里我精心挑选的单引号,全给我改成双引号了。提交代码后CI检查失败,同事看我的眼神都不对了。第二次学乖了点,用Python的Black,结果发现它把我一个好好的长列表,硬是拆成一行一个元素,代码看着是规矩了,但可读性反而直线下降,我自己都快不认识了。第三次更离谱,团队里有人用ESLint,有人用Standard,改来改去的,最后合并冲突的代码量比我们写的还多。


先看核心对比:5款工具一句话总结

后来我花了一整周,把市面上主流的5款格式化工具全给测了一遍,从JS到Python再到Go,从配置到性能,踩过的坑都能写本书了。今天直接给你上干货,绝不废话。

| 工具 | 适用语言 | 核心理念 | 配置自由度 | 速度(1000行文件) |
|——|———-|———-|————|——————-|
| Prettier | JS/TS/HTML/CSS/JSON等 | 意见独裁者 | 极低 | 极快 |
| ESLint + Prettier | JS/TS | 规则可定制 | 中高 | 较快 |
| Black | Python | 不可配置的美 | 零 | 极快 |
| gofmt | Go | 官方标准 | 零 | 极快 |
| dprint | 多语言 | 性能优先 | 中等 | 极快 |

注:以上速度数据基于个人测试环境,实际表现可能因硬件和文件类型而异,仅供参考。

我的选择建议: 听我的,别纠结。写JS/TS项目,无脑上Prettier + ESLint组合,真的好用;Python项目就用Black,省心;Go项目用gofmt,根本没得选,官方最大;如果你们团队对性能有极致要求,比如编译一次能省好几杯咖啡钱,那试试dprint,它用Rust写的,快得跟作弊一样。


第一个坑:Prettier的“独裁”会让你哭

Prettier的理念我一开始是拒绝的,凭什么不让我控制大括号要不要换行?官方文档文档不够清晰,我翻了半天才发现,能配置的选项加起来也就20多个,少得可怜。

但你用久了就会发现,这恰恰是它最牛的地方。团队里再也不用争论“缩进用2空格还是4空格”这种无聊问题了,因为Prettier说了算,谁也别bb。

javascript
// 他写的原始代码,看着就累
const result = await fetch(
'https://api.example.com/data',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'test' })
}
)

Prettier格式化后会变成这样,清爽多了:

javascript
// Prettier格式化后,舒服
const result = await fetch('https://api.example.com/data', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'test' })
})

为啥这么写? Prettier有个“最优换行算法”,它会判断如果参数能在一行内放下,就合并;放不下才换行。目的就是为了让你在任何屏幕宽度下看着都顺眼。

但有个致命问题,一开始我搞错了: Prettier默认会把所有字符串改成双引号。如果你项目用的是单引号风格,一定要在.prettierrc里加这行配置:

json
{
"singleQuote": true,
"trailingComma": "all",
"tabWidth": 2,
"printWidth": 100
}

否则等着被同事骂吧,我亲身经历,血的教训。


另一个坑:ESLint + Prettier组合的正确姿势

很多人把ESLint当格式化工具用,这就是个误区。ESLint的定位是“代码质量检查”,格式化只是它的副业。真正专业的做法是:ESLint负责抓错,Prettier负责排版,分工明确,互不干涉。

我见过最蠢的配置,是把ESLint的indent规则和Prettier的缩进同时开着,结果格式化完,又被ESLint给改回去,循环反复,合并冲突一大片,那场面简直了。

正确做法是用eslint-config-prettier把ESLint里跟Prettier冲突的规则全关掉,就像这样:

javascript
// .eslintrc.js
module.exports = {
extends: [
'eslint:recommended',
'plugin:react/recommended',
'prettier' // 记住,这个必须放最后,才能覆盖前面的规则
],
plugins: ['prettier'],
rules: {
'prettier/prettier': 'error' // 把Prettier当作ESLint规则来执行
}
}

为啥要这么写? 因为prettier规则放到extends最后面,它会覆盖前面所有可能冲突的格式化规则。这样你执行eslint --fix的时候,实际上是在跑Prettier的格式化,同时还能检查出未使用的变量这类逻辑错误,一举两得。

顺手说下性能数据,我们5个人测过一个1000行的React组件:

  • 只用ESLint格式化:1.8秒
  • 只用Prettier格式化:0.8秒
  • 组合使用:1.2秒(因为ESLint要先解析AST再交给Prettier)

虽然慢了一丢丢,但换来的可是代码质量+格式的双重保障,值了!

(核心对比图:一张表格或流程图,展示ESLint、Prettier、Black三者的工作流程和覆盖范围,配上“组合使用效果最佳”的标注)


再说Python:Black的霸道与合理

做Python开发的都知道PEP 8,但PEP 8就是个指南,不是工具。Black直接把这个指南变成了硬性规则,霸道得一批。

来看看Black怎么处理那个经典的“行长超过79字符”问题,这才是精髓:

python
# 原始代码
result = some_function_with_long_name(param1="value1", param2="value2", param3="value3", param4="value4")

# Black格式化后
result = some_function_with_long_name(
param1="value1",
param2="value2",
param3="value3",
param4="value4",
)

注意那个逗号! Black会在最后一项后面也加逗号,这是PEP 8推荐的“尾随逗号”风格。好处是以后添加新参数时,git diff只显示新增那行,不会修改旧行,代码审查看着特别清爽。

但有个让我抓狂的地方:Black默认将字符串改为双引号。我习惯了单引号,每次格式化完都要手动改回去,真的烦。官方给的理由是“统一风格”,但我个人觉得这跟Python社区主流习惯不符。后来我发现可以用--skip-string-normalization参数禁用,或者加到配置里,通过skip-string-normalization = true可保留原始引号风格,这个好用:

toml
# pyproject.toml
[tool.black]
line-length = 88
skip-string-normalization = true

这样Black就不会动你的引号了,舒服多了。


Go语言:gofmt,没得选就是最好的选择

Go语言在这方面做得最绝——官方直接给你一个格式化工具,而且没有任何配置选项。你写出来的代码如果不符合规范,连编译都过不了。

刚开始我觉得这太霸道了,但用久了发现,这反而是最省心的方案。因为所有Go代码看起来都一模一样,你从GitHub上随便拉一个Go项目,打开代码风格跟你自己写的一模一样,阅读成本几乎为零。

而且gofmt有个隐藏技能:它不只是格式化,还会做一些简单的代码优化。比如它会自动把if err != nil { return err }这种模式整理得更紧凑,甚至能检测出一些不必要的变量声明。

性能方面,gofmt快得离谱。 我们测过一个5000行的Go文件,格式化只用了0.05秒,基本就是瞬间完成。这得益于Go的AST解析器设计得极其高效。


性能怪兽:dprint,Rust写的快如闪电

如果你对格式化速度有变态要求,比如每次保存都要格式化整个项目,那dprint就是为你准备的。

dprint是用Rust写的,支持JavaScript、TypeScript、JSON、Markdown等多种语言。它的设计理念是“性能优先”,格式化速度比Prettier快10倍以上。

我试过一个极端场景:一个包含200个文件的TypeScript项目,Prettier格式化需要12秒,dprint只用了1.2秒。这差距,够你泡杯咖啡了。

配置方面,dprint的配置文件是JSON格式,跟Prettier很像,但多了很多性能相关的选项:

json
{
"indentWidth": 2,
"lineWidth": 100,
"typescript": {
"quoteStyle": "alwaysSingle"
}
}

但有个坑: dprint的生态还不够完善,有些Prettier的插件(比如处理GraphQL、YAML的)在dprint上还没有对应的实现。所以如果你项目里用了很多冷门语言,可能还是得用Prettier。


终极建议:怎么选?看这张决策图

说了这么多,最后给你一个简单粗暴的选择标准:

  • 项目全是JS/TS: Prettier + ESLint组合,没毛病
  • 项目全是Python: Black,省心省力
  • 项目全是Go: gofmt,没得选
  • 多语言混搭项目: 试试dprint,性能怪兽
  • 团队有历史遗留代码: 先用Prettier格式化一遍,再上ESLint检查,别一次性改太多

最后送你一句话:格式化工具不是用来争论的,是用来解放生产力的。 选一个团队都同意的,然后忘掉它,把精力花在写代码上。

你踩过哪些格式化工具的坑?欢迎在评论区分享,咱们一起吐槽。

滚动至顶部