基本介绍

Prettier 是一个代码风格修正工具。官网:https://prettier.io/

代码风格是所有程序员都要遇到的问题,不管是团队协作还是个人:

  • 有的喜欢有分号,代码更安全;有的喜欢没分号,能少打一个字符;
  • 有的喜欢单引号,能少按一下 Shift;有的喜欢反引号,扩展更高;
  • camelCase、PascalCase、snake_case 总是在团队里无法统一;

代码风格太主观了,根本无法让谁信服谁,也没有绝对的是非对错。有没有办法自动格式化,统一代码风格?

Prettier 是一个流行的代码格式化工具,它可以自动调整代码的样式,使其更具可读性和一致性。它支持多种编程语言,包括 JavaScript、TypeScript、HTML、CSS、SCSS、GraphQL、JSON、Markdown 等。

Prettier 的核心特点包括:

  • 一致的代码风格:Prettier 可以帮助团队成员统一代码风格,减少代码审查时关于代码格式的讨论。
  • 集成多种编辑器:Prettier 支持许多流行的代码编辑器,如 Visual Studio Code、Sublime Text、Atom 等都有相应的插件,可以在编写代码时自动运行 Prettier。
  • 自动格式化:Prettier 可以自动格式化文件,无需手动调整代码格式。
  • 无需配置:Prettier 的默认配置就足以满足大多数项目的需求。使用 Prettier 时,通常不需要花费时间调整和维护配置文件。
  • 可配置性:虽然 Prettier 默认配置通常已经足够,但它仍支持自定义配置。你可以在项目根目录下创建一个 .prettierrc 文件,根据项目需求调整格式化选项。
  • 支持多种语言:Prettier 支持多种编程语言和文件格式,提供广泛的适用性。

其实在很早之前已经有人开始研究哪种方式来格式化长文本是最好的(Prettier Printer),比如 Philip Wadler 在 《A prettier printer》这里给出了一些自动格式化换行的理论依据:

A good pretty printer must strike a balance between ease of use, flexibility of format, and optimality of output.

Prettier 的作者 James 在这篇论文基础上再完善了一些代码风格规则,最终成为了 Prettier 格式化代码的最终方案。比如像下面的链式调用,Prettier 输出的就比原来论文描述的要好看一些:

// 原版 "A prettier printer" 的实现
hello().then(() => {
  something()
}).catch(console.error)
 
 
// Prettier 的实现
hello()
  .then(() => {
    something()
  })
  .catch(console.error)

工作原理

Prettier 是如何能够做到代码的格式化?

首先,Prettier 会把代码转换成 AST(抽象语法树),这里用到的是一个叫 Recast 的库,而 Recast 实际上也用了 Esprima 来解析 ES6。

所以无论之前的代码怎么乱、怎么屎,Prettier 都抹掉之前的所有样式,抽成最本质的语法树。然后再用 Prettier 的代码风格规则来输出格式化后的代码。

Prettier 能够支持的格式化语言是多种多样的,并非仅仅只为 JS 服务。理论上来讲,只要把一门语言的代码抽象为语法树,然后再有对应的格式化规则,那么无论什么语言都是可以的。

Prettier 官方以及社区就提供了一些插件,通过使用插件,可以添加对新语言和文件类型的支持,让 Prettier 格式化更多种类的代码。Prettier 插件通常是单独的 npm 包,需要安装它们作为项目的依赖。插件的名称通常遵循 prettier-plugin-* 的命名规范。安装插件后,Prettier 会自动发现并使用它们。

以下是一些常见的 Prettier 插件示例:

  • prettier-plugin-svelte:这个插件为 Svelte 组件提供了格式化支持。安装这个插件后,可以使用 Prettier 格式化 Svelte 文件。
  • prettier-plugin-toml:这个插件为 TOML 配置文件提供了格式化支持。安装这个插件后,可以使用 Prettier 格式化 TOML 文件。
  • prettier-plugin-java:这个插件为 Java 语言提供了格式化支持。安装这个插件后,可以使用 Prettier 格式化 Java 文件。
  • prettier-plugin-php:这个插件为 PHP 语言提供了格式化支持。安装这个插件后,可以使用 Prettier 格式化 PHP 文件。

Opinionated VS. Unopinionated

另外,Prettier 的官方文档里一直在强调自己是一个 Opinionated(固执己见的)的工具,这里想展开聊聊 Opinionated。

其实不仅 Prettier,我们日常使用的一些库和框架都会标明自己是 opinionated 还是 unopinionated:

按照框架/库的 opinionated 还是 unopinionated 思路来使用它们非常重要:

  • Opinionated 的思路是“你的一切我全包了,使用者就别自己发明设计模式和轮子,用我的就行,有锅我背。”
  • Unopinionated 的思路则是“我就给你一堆零件,每个有优有劣,自己组装来玩吧。”

Prettier 属于 Opinionated 哲学,这意味着它提供的代码风格已经是最优的,不希望使用者做太多自定义的内容,而应该相信 Prettier 已经服务到位了。

快速上手

新建一个项目,使用 pnpm init 进行初始化,安装 prettier

pnpm add --save-dev --save-exact prettier
  • --save-exact:在 package.json 里面记录具体的版本号

package.json 里面添加命令行脚本:

"scripts": {
    // ...
    "format": "prettier --write ./src"
},

之后就可以使用 pnpm format 这条命令来进行格式化代码操作。

也可以通过安装 VSCode 插件的方式来使用 Prettier。使用脚本命令和使用 VSCode 插件两者之间的差别如下:

  • 实时性:使用 Prettier 的 VSCode 插件,可以在编写代码时立即看到格式化效果,而不需要等待执行脚本命令。这有助于在编写代码时就保持良好的代码风格。
  • 范围:通过运行脚本命令 "prettier --write .",可以一次性格式化整个项目中的所有文件。而 VSCode 插件只会在你需要时(如保存文件)格式化当前打开的文件。

如果想要自定义规则,可以在项目根目录下面创建一个 .prettierrc 文件,之后使用对象的形式写入自定义规则即可:

{
  "singleQuote": true,
  "semi": false,
  "printWidth": 120,
  "useTabs": false,
  "tabWidth": 2,
  "bracketSpacing": true,
  "trailingComma": "all",
  "arrowParens": "avoid"
}
  • singleQuote:使用单引号而不是双引号
  • semi:在所有代码语句的末尾添加分号
  • printWidth:每行代码的长度限制
  • useTabs:使用制表符缩进,而不是空格缩进
  • tabWidth:指定一个制表符等于的空格数
  • bracketSpacing:在对象字面量的花括号内侧使用空格作为间隔
  • trailingComma:指定添加尾后逗号的方式
    • none:无尾后逗号
    • es5:在 ES5 中有效的尾后逗号(如对象与数组等)
    • all:尽可能添加尾后逗号(如函数的参数列表)
  • arrowParens:箭头函数仅有一个参数时,参数是否添加括号

详见 Prettier 格式化规则