跳到主要内容

用 EditorConfig 统一团队编码风格:缩进、换行符、字符集一次说清

讲清 .editorconfig 怎么让全队编辑器在缩进、换行符、字符集、行尾空白上保持一致,跟 Prettier 的分工区别,以及常用配置项怎么写才不互相打架。

发布于 作者 李雷
#editorconfig #代码风格 #团队协作 #前端工程

用 EditorConfig 统一团队编码风格:缩进、换行符、字符集一次说清

团队里最磨人的不是难写的逻辑,是每个 PR 里那一堆只改了空白的 diff。一个人编辑器用 Tab,另一个用 4 空格,一个在 Windows 上写出 CRLF,另一个在 Linux 上是 LF。真正的改动两行,diff 里却红绿满屏,审查的人翻半天才找到那两行。.editorconfig 就是解决这一层问题的文件:它让团队里每个人的编辑器在打开文件那一刻就对齐缩进、换行符和字符集,不需要任何构建步骤,也不挑编辑器。

.editorconfig 到底管什么

它管的是编辑器的底层行为,粒度很具体。最常用的几个键:

  • indent_style:space 还是 tab,决定按一下 Tab 键插入的是空格还是制表符。
  • indent_size:一级缩进多少个空格。注意,如果 indent_style = tab,这个值只影响一个 Tab 显示多宽,不会真的插空格。
  • end_of_line:lfcrlfcr,统一换行符。跨平台团队基本都该锁 lf
  • charset:一般写 utf-8
  • trim_trailing_whitespace:保存时裁掉行末空白。
  • insert_final_newline:文件末尾补一个空行。
  • max_line_length:提示最大行宽。

这些设置一打开文件就生效,在你按下保存之前编辑器就已经按规则走,所以它修的是"源头",而不是事后补救。想可视化地把这些键拼出来、实时看到输出文件,可以用 /zh/t/editorconfig-generator/,左边勾选右边直接出 .editorconfig 内容,复制就能用。

跟 Prettier、ESLint 是什么关系

这是最常被问的一点。它们不冲突,是不同层。EditorConfig 管的是编辑器底层行为,任何装了插件的编辑器都认,不需要 Node、不需要构建,一个临时贡献者克隆完仓库、还没保存,缩进就已经对了。Prettier 和 ESLint 是格式化器和检查器,在保存时或 CI 里重写、标记代码,而且只在装了它们的地方才跑。

大多数成熟团队两个一起用:EditorConfig 负责让所有人的编辑器在保存前就和仓库一致,Prettier / ESLint 做强制收口那一道。唯一要小心的是它们在 indent_size 上有重叠,两边的缩进配置必须对齐,否则保存时一个写 2 空格、另一个改回 4 空格,来回打架。

一段真实的 .editorconfig

下面是我自己一个前后端混合仓库里实际用的配置,直接贴出来:

root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 2

[*.py]
indent_size = 4

[Makefile]
indent_style = tab

[*.md]
trim_trailing_whitespace = false

几个点值得说清楚。root = true 放在最顶上,作用是让 EditorConfig 不再往父目录继续找配置。EditorConfig 打开文件时会从当前目录一路往上合并每一个 .editorconfig,如果你不写这行,home 目录或 monorepo 父级里某个乱放的配置就可能泄进来。[*] 段必须放最前面,后面的窄 glob 段会覆盖它里面设过的键。所以 [*.py] 把 Python 改成 4 空格,[Makefile] 强制用 Tab(GNU Make 的 recipe 行用空格开头会直接报 missing separator),[*.md] 关掉末尾空白裁剪,因为 Markdown 里行末两个空格表示硬换行,裁掉换行就没了。

glob 优先级和那些容易踩的坑

EditorConfig 从上往下读各段,后面匹配的段覆盖前面段里它设过的键,后面没提到的属性沿用前面的值。所以顺序是铁律:宽的 [*] 永远在最前,[*.md][*.{js,ts}] 这种窄 glob 放下面。把窄 glob 放到 [*] 上面是新手最常见的错,放在它之后的宽 [*] 会反过来把你的覆盖盖掉。

我自己被坑过一次的是 indent_styleindent_size 的组合:想要两空格缩进,只改了 indent_size = 2,却忘了 indent_style 还是 tab,结果文件照样按 Tab 缩,indent_size 只是让那个 Tab 显示成两格宽而已。要真的插空格,这两个键得一起设。这种问题肉眼很难发现,因为显示出来"看着像两空格",提交后别人那边一对照才露馅。

配套的几个配置文件

.editorconfig 往往不是孤立的。锁换行符时它配上 .gitattributes 里的 * text=auto eol=lf 是双保险;仓库根目录通常还会有 /zh/t/gitignore-generator/ 生成的 .gitignore 控制忽略项,以及 /zh/t/robots-txt-generator/ 这类站点配置文件。这些都是仓库根目录那一排"看不见但每天在生效"的小文件,一次配好,规则就随仓库带给每个未来的协作者,不用再写一段没人看的 CONTRIBUTING 说明。

.editorconfig 提交进仓库的成本不到一分钟,省下的是之后每一个 PR 里翻幽灵 diff 的时间。对一个长期维护、有多人协作的项目来说,这是性价比最高的一步基础设施。


Made by Toolora · Updated 2026-06-13