5月27日 22:04

Prettier 插件有哪些?如何开发自定义插件?

直接回答

Prettier 支持两类插件:语言解析器插件(为新语言提供格式化能力)和格式化增强插件(扩展现有语言的格式化行为)。开发自定义插件需实现三个核心部分:languages(语言定义)、parsers(解析器,文本→AST)、printers(打印器,AST→格式化文本)。

Prettier 插件分类

语言解析器插件 — 让 Prettier 支持新语言:

  • @prettier/plugin-php@prettier/plugin-ruby@prettier/plugin-pug

格式化增强插件 — 对已有语言做额外处理:

  • prettier-plugin-organize-imports:自动排序 import
  • prettier-plugin-tailwindcss:Tailwind 类名排序
  • prettier-plugin-sort-json:JSON 键排序

安装后在 .prettierrcplugins 数组中声明即可。Prettier 也会自动加载 node_modules 下匹配 prettier-plugin-*@scope/prettier-plugin-* 的包。

如何开发自定义插件

一个完整的插件至少导出 languagesparsersprinters

javascript
// my-prettier-plugin/index.js module.exports = { languages: [ { name: "MyLang", parsers: ["mylang-parse"], extensions: [".mylang"], }, ], parsers: { "mylang-parse": { parse: (text) => { // 将源码文本解析为 AST // 可借助第三方解析器(如 babel, tree-sitter 等) return customParse(text); }, astFormat: "mylang-ast", locStart: (node) => node.start, locEnd: (node) => node.end, }, }, printers: { "mylang-ast": { print: (path, options, print) => { // 将 AST 节点转换为 Prettier Doc 对象 // Doc 是 Prettier 的中间表示,支持换行、缩进等 const node = path.getValue(); // 用 concat/line/hardline 等构建输出 }, }, }, };

开发要点:

  • parse 函数的输入是源码字符串,返回 AST 对象
  • locStart/locEnd 告诉 Prettier 每个 AST 节点的位置,用于错误定位
  • print 函数返回 Doc 对象,用 concathardlineindent 等 API 拼接格式化输出
  • 如果只想对已有语言做预处理,只需在 parser 中实现 preprocess 函数,无需写完整 parser/printer

调试方式: 运行 prettier --plugin ./my-prettier-plugin --debug-print-doc file.mylang 可查看生成的 Doc 结构。

面试追问方向

  1. 如果只想在格式化前对代码做预处理(如删除注释),怎么实现? — 在对应 parser 中实现 preprocess 函数即可,不需要自定义整个 parser/printer 链路。

  2. Prettier 的 Doc 是什么? — Prettier 内部的中间表示,类似虚拟 DOM。print 返回 Doc 而非字符串,Prettier 再根据行宽等配置将 Doc "渲染"为最终输出,这样能自动处理换行和缩进。

  3. 插件和 Prettier 内置语言支持的区别? — 内置语言是 Prettier 核心代码的一部分,性能和兼容性更优;插件是独立模块,更新节奏自由但需自行维护与 Prettier 版本的兼容。

标签:Prettier