Prettier 深度解析(一):设计哲学、配置文件与常见配置项

说实话,我刚开始用 Prettier 的时候,心里是有点抵触的。

你想啊,一个工具连你代码怎么换行都要管,是不是管得太宽了?但后来我在一个 10 人团队里做代码评审,发现每个人写的代码风格都不一样——有人喜欢单引号,有人坚持双引号;有人行尾加分号,有人觉得那是多余。每次合并代码,光改这些格式问题就能吵半天。

直到我把 Prettier 引入项目,世界才清净了。今天我们就来聊聊这个「代码格式界的独裁者」——Prettier。

一、Prettier 的设计哲学:少即是多

Prettier 的核心思想其实就一句话:它不关心你的代码写得对不对,只关心你的代码长得好不好看

说白了,它是一个「固执己见」的格式化工具。你给它一段乱七八糟的代码,它吐出来的一定是它认为最漂亮的版本。而且它几乎不给你讨价还价的余地——配置项少得可怜,跟 ESLint 那种动辄上百条规则比起来,Prettier 简直像个极简主义者。

Prettier 的三大设计原则:

  • 可读性优先:所有格式化规则都围绕「让代码更容易阅读」这个目标
  • 输出确定性:同样的输入,永远得到同样的输出,不会因为心情好坏改变格式
  • 配置最小化:能不改就不改,默认配置已经足够好

我记得有一次,团队里有个新人问我:「为什么 Prettier 要把我的三元运算符拆成三行?我觉得一行更简洁啊。」

我当时的回答是:「你觉得一行简洁,但 Prettier 觉得一行太长,影响阅读。它不会跟你商量,因为它知道什么对团队最好。」

嗯,这就是 Prettier 的哲学——放弃个人审美,拥抱统一标准

二、配置文件(.prettierrc)详解

Prettier 支持多种配置文件格式,我个人最常用的是 .prettierrc 的 JSON 格式,简单直观。

2.1 支持的配置文件格式

格式 文件名 示例
JSON .prettierrc.prettierrc.json { "semi": false }
YAML .prettierrc.yaml.prettierrc.yml semi: false
TOML .prettierrc.toml semi = false
JS prettier.config.js.prettierrc.js module.exports = { semi: false }
package.json package.json 中添加 prettier 字段 "prettier": { "semi": false }

我建议团队项目统一使用 .prettierrc 文件,放在项目根目录。这样每个人进来一看就知道格式规则在哪,不用去翻 package.json。

2.2 配置文件的优先级

Prettier 查找配置文件的顺序是这样的:

  1. 先找当前文件所在目录的配置文件
  2. 如果没找到,往父目录找,直到项目根目录
  3. 如果还没找到,用用户主目录下的全局配置
  4. 最后才是默认配置

小技巧: 如果你想让某个子目录使用不同的格式规则,可以在该目录下放一个独立的 .prettierrc 文件。我曾经在一个 monorepo 项目里,给前端和后端分别配置了不同的 printWidth,因为后端代码逻辑复杂,需要更宽的行宽来展示完整逻辑。

三、常见配置项详解

Prettier 的配置项虽然少,但每个都很关键。下面我挑几个最常用的,结合我的实际经验来讲。

3.1 printWidth:一行多长才算长?

默认值是 80,单位是字符。这个值决定了 Prettier 什么时候该换行。

// 当 printWidth = 80 时,这行代码会被换行
const veryLongVariableName = someFunction(argument1, argument2, argument3, argument4, argument5);

// 格式化后:
const veryLongVariableName = someFunction(
  argument1,
  argument2,
  argument3,
  argument4,
  argument5
);

我个人习惯把 printWidth 设为 100。为什么?因为现在的显示器都宽了,80 个字符太浪费空间。但我也见过一些老派开发者坚持用 80,说是在终端里看代码更舒服。嗯,这个看团队习惯吧。

注意: printWidth 不是硬限制,而是一个「建议值」。Prettier 会尽量让代码不超过这个宽度,但如果实在没办法(比如一个很长的 URL 字符串),它也不会强行截断。

3.2 tabWidth:缩进用几个空格?

默认值是 2。这个配置决定了每个缩进级别用几个空格。

// tabWidth = 2
function foo() {
  if (true) {
    console.log('hello');
  }
}

// tabWidth = 4
function foo() {
    if (true) {
        console.log('hello');
    }
}

我曾经在一个老项目里看到 tabWidth 设为 8,那代码缩进简直像楼梯一样,嵌套三层就看不到右边了。后来我果断改成了 2,世界瞬间清爽了。

3.3 semi:分号到底要不要?

默认值是 true,也就是要加分号。但很多 JavaScript 开发者喜欢不加分号,觉得代码更简洁。

// semi: true
const a = 1;
const b = 2;

// semi: false
const a = 1
const b = 2

这里我要说一个坑:如果你选择不加分号,一定要确保代码不会因为 ASI(自动分号插入)机制出问题

我曾经遇到过这样一个 bug:

// 没有分号的情况下
const value = someFunction()
[1, 2, 3].forEach(item => console.log(item))

// 实际上被解析成了:
const value = someFunction()[1, 2, 3].forEach(item => console.log(item))
// 直接报错!

所以我的建议是:新项目可以不加分号,但老项目保持原样。不要为了追求「简洁」而引入潜在的 bug。

3.4 singleQuote:单引号还是双引号?

默认值是 false,也就是用双引号。我个人更喜欢单引号,因为少按一个 Shift 键。

// singleQuote: true
const name = 'hello world'

// singleQuote: false
const name = "hello world"

避坑指南: 如果你在写 JSX,Prettier 会自动把 JSX 属性里的引号强制改成双引号,不管你怎么配置 singleQuote。这是因为 JSX 规范要求属性值用双引号。嗯,这个没办法,Prettier 就是这么固执。

3.5 trailingComma:尾逗号要不要?

默认值是 'es5',也就是在 ES5 允许的地方加尾逗号(比如对象和数组)。

// trailingComma: 'es5'
const obj = {
  name: 'Alice',
  age: 30,  // 这里加了逗号
}

// trailingComma: 'none'
const obj = {
  name: 'Alice',
  age: 30  // 没有逗号
}

我个人强烈建议开启尾逗号。为什么?因为当你新增一行时,不需要修改上一行。这样 git diff 会更干净,只显示新增的行,而不是「新增一行 + 修改上一行加逗号」。

3.6 bracketSpacing:对象括号内要不要空格?

默认值是 true,也就是在花括号内加空格。

// bracketSpacing: true
const obj = { foo: 'bar' }

// bracketSpacing: false
const obj = {foo: 'bar'}

这个纯粹是审美问题。我个人觉得加空格更易读,但如果你喜欢紧凑风格,也可以关掉。

四、知识体系结构图

下面我用一张 SVG 图来总结 Prettier 的核心知识体系:

Prettier 核心 设计哲学 配置文件 常见配置项 可读性优先 输出确定性 配置最小化 JSON / YAML / JS 格式 优先级:就近原则 支持 .prettierignore printWidth / tabWidth semi / singleQuote trailingComma / bracketSpacing 核心:放弃个人审美,拥抱统一标准

五、一个完整的配置示例

最后,给你看看我常用的配置,你可以直接拿去用:

{
  "printWidth": 100,
  "tabWidth": 2,
  "useTabs": false,
  "semi": true,
  "singleQuote": true,
  "trailingComma": "es5",
  "bracketSpacing": true,
  "arrowParens": "always",
  "endOfLine": "lf"
}

这个配置我用了好几年,在多个项目里验证过,基本没出过问题。当然,你也可以根据自己的喜好调整。记住一点:配置定了就别轻易改,否则团队又要重新适应。

好了,关于 Prettier 的设计哲学和配置项,今天就聊到这里。下一节我们会深入 Prettier 的解析器和插件机制,看看它到底是怎么把代码「变好看」的。


专注资料整理