为什么选择 Prettier:一份“固执己见“的代码格式化器采纳指南
为什么选择 Prettier一份固执己见的代码格式化器采纳指南【免费下载链接】prettierPrettier is an opinionated code formatter.项目地址: https://gitcode.com/gh_mirrors/pr/prettierPrettier 是一个固执己见opinionated的代码格式化器它解析你的代码、剥离原有排版再按自身规则重新打印。本文基于仓库官方文档《Why Prettier?》系统梳理团队采纳 Prettier 的六大核心理由、背后的打印算法与选项冻结哲学并给出从 CLI、配置文件到 pre-commit 钩子的完整落地路径。读完本文你将理解为什么要用 Prettier以及如何低成本地把 Prettier 引入团队与存量代码库。先理解核心前提什么是固执己见的格式化器Prettier 不是那种你想怎么排版就怎么排版的万能工具。正如 docs/index.md 所述它移除所有原始样式并确保所有输出代码符合一致的风格支持 JavaScript含实验特性、JSX、Angular、Vue、Flow、TypeScript、CSS/Less/SCSS、HTML、Ember/Handlebars、JSON、GraphQL、Markdown含 GFM 与 MDX v1、YAML、Lightning Web Components 与 MJML 等众多语言。它的工作方式与一般调整缩进的工具截然不同解析代码得到 AST忽略原有排版再按自己的规则、以行宽为约束重新打印。例如下面这行代码因为能放进一行而保持不变foo(arg1, arg2, arg3, arg4);而当调用过长、单行放不下时foo(reallyLongArg(), omgSoManyParameters(), IShouldRefactorThis(), isThereSeriouslyAnotherOne());Prettier 会不辞辛劳地为你重排成foo( reallyLongArg(), omgSoManyParameters(), IShouldRefactorThis(), isThereSeriouslyAnotherOne(), );这种解析—重印模型正是官方文档中所有为什么值得采纳的论证的技术底座风格由工具一次性、确定性地给出讨论空间被压缩到最小。那么团队到底为什么要引入它官方文档给出了六大理由。理由一终结风格之争建立并强制执行风格指南官方文档将采纳 Prettier 的最大理由归结为一句话停止没完没了的代码风格争论。普遍公认团队拥有统一风格指南是有价值的但达成这一目标的过程痛苦且毫无成就感——人们会为具体的写法动情绪没人喜欢花时间写下或接收风格 nit吹毛求疵的修改意见。那么为什么选择Prettier 风格指南而不是其他任意一套风格指南答案是Prettier 是唯一全自动的风格指南。即使它不能 100% 按你的喜好格式化代码考虑到其独一无二的收益这种牺牲也是值得的。文档记录了当时社区的真实声音我们希望解放大脑线程结束围绕风格的讨论。这类讨论偶尔有产出但绝大多数时候是浪费。真的有一位工程师花了巨大精力清理我们全部代码因为我们争论三元表达式的写法争论了很久而且执行得并不一致。这很蠢但这就是一场持续的伟大辩论消耗了大量来回扯皮的时间。现在达成一致容易多了直接跑 Prettier跟随它的风格。受够了告诉别人怎么排版他们的产品代码。我们的首要理由就是停止浪费时间争论风格 nit。配好 githook 之后PR 里因为 ESLint 规则导致的风格问题、以及我需要事后 nit 或清理的东西都变少了。我不想再让任何人对任何人吹毛求疵。这让我想起史蒂夫·乔布斯每天穿同样的衣服——他有上百万个决策要做不想被挑衣服这种琐事打扰。我觉得 Prettier 就是这样的存在。从仓库源码看这种全自动承诺由 src/main/core.js 中的coreFormat流水线兑现parseText解析文本 →printAstToDoc将 AST 转为中间表示 Doc →printDocToString最终打印为字符串。用户提交什么排版都无所谓因为原始样式在解析阶段就被剥离了。理由二让新人更快上手Prettier 通常由对代码库和 JavaScript 有经验的人引入但从中获益不成比例的人群恰恰是代码库的新人。有人可能以为它只对编程经验很少的人有用但官方文档指出经验丰富的工程师刚加入公司时他们此前可能用着完全不同的编码风格、以及从其他编程语言转来的开发者都能明显加快上手速度。文档引用的真实反馈我使用 Prettier 的动机是让自己看起来懂怎么把 JavaScript 写好。我总是把空格放错位置现在我不用再担心这个了。初学者会犯大量由语法引起的错误。有了 Prettier你可以减少这类错误省下大量时间专注真正重要的事。作为老师我也会让我的学生安装 Prettier帮助他们学习 JS 语法并拥有可读的文件。这一理由呼应了 docs/rationale.md 中正确性优先的原则Prettier 的第一要求是输出与格式化前行为完全一致的合法代码任何违背该原则的输出都被视为需要修复的 bug。新人不用担心这样写会不会破坏格式只需关注语义正确性。理由三把心智留给写代码而不是排版一旦人们开始使用 Prettier往往会意识到过去自己其实花费了大量时间和脑力在手动排版上。配合编辑器集成只需按下那个魔法快捷键代码瞬间被格式化——这是极具冲击力的体验。文档中的声音我想写代码而不是把时间花在排版上。它移除了我们日常生活中那 5% 让人不爽的部分——也就是排版。都 2017 年了当你多加一个参数导致调用超过 80 列、还得手动把调用拆成多行时依然很痛苦。编辑器集成之所以能实现保存即格式化且不打扰光标位置源于 src/main/core.js 中formatWithCursor的实现格式化前先从 AST 定位光标所在的最小区域格式化时记录该区域被打印到何处再通过一次仅允许插入与删除的 diff 把光标符号放回格式化后的正确位置。这也是为什么按下快捷键代码就整齐了、光标还不乱跑这种体验是工程上被认真设计过的。理由四风格低争议易于被团队接受Prettier 团队在选型上刻意使用了最不具争议性的编码风格经过多轮修复所有边缘情况、打磨上手体验。官方文档承诺当你准备把 Prettier 推入代码库时不仅技术层面应该毫无痛苦新格式化的代码库也不应引发大规模争议能被同事顺利接受。当时的社区反馈开销很低。我们能不费什么功夫就把 Prettier 扔到各种非常不同的仓库里。基本没有 bug。如果在实施过程中出现大的风格问题我们会对把它扔到 JS 代码库上心存顾虑。我很高兴地说并没有。每个人都把它跑在 pre-commit 脚本里我们中还有几个人也用保存时格式化的编辑器扩展。它很快对一个我们较大的 JS 代码库跑 Prettier 只要 13 秒以内。对我们来说Prettier 最大的好处是能一次性格式化整个代码库。注意这些引用是文档撰写年代的记录13 秒针对的是当时某个特定仓库不应理解为普适性能指标但它佐证了一次性全量格式化在设计上的可行性。理由五清理存量代码库快速见效制定并强制执行一套编码风格是巨大的工程因此它常常被搁置最终团队面对的往往是风格混乱的历史代码。这种场景下运行 Prettier 是快速取胜几乎不用花时间代码库就变得统一、易读。文档引述看看这些代码吧——我只是想恢复理智。我们接手了一个约 2000 个模块的 ES6 代码库由 20 位开发者历时 18 个月、在全球团队中开发完成。没做多少调研就感觉赢麻了。仓库中的 prettier.config.js 展示了 Prettier 项目自身如何以身作则它通过overrides对**/*.{js,mjs,cjs}指定meriyah解析器、对bin/prettier.cjs关闭尾逗号、对tsconfig.json等 JSON 文件使用jsonc解析器——存量代码库正是通过这类可提交的配置文件获得确定性的统一风格。理由六社区势能历史视角文档指出人们选择 Prettier 时并不只看纯技术因素谁构建了它、谁在使用它、它在社区中传播得多快都会产生不小的影响。当时的反馈包括发布两个月就被几乎所有主流 JS 项目采用由 React 与 React Native 的同班人马构建等。需要说明的是这些引用保留的是文档撰写年代的社区观感如7000 stars100,000 npm downloads/mo属于历史证言而非当前数据。今天判断 Prettier 的地位更可靠的依据是仓库自身生态Prettier 拥有成熟的插件体系本仓库即包含 plugin-hermes、plugin-oxc、plugin-yuku 等多个实验性解析器插件这本身就是社区围绕它持续共建的持续证据。原理纵深为什么它能全自动打印要理解全自动风格指南为何可行需要看 Prettier 的打印算法。如 docs/technical-details.md 所述其打印器以 Wadler 论文《A prettier printer》描述的算法为内核打印机接收 AST返回输出的中间表示IR再据此生成字符串。关键优势是打印机可以丈量IR判断输出是否放得下一行放不下就在指定位置换行。以[(, line, arg, line, )]为例它表示左括号、参数、右括号的拼接如果整体放不进一行打印机就会在标记了line的地方断行。AST 到 Doc 的递归转换由 src/main/ast-to-doc.js 完成它沿着AstPath栈递归下降调用插件提供的print()函数生成 Doc。Doc 是 Prettier 的中间表示其完整命令族见 commands.mdgroup标记一组尽量放在一行的内容放不下时先打破最外层 group逐层尝试直至全部放下line/softline/hardline分别表示放得下就变空格放得下就消失无论如何都换行三种断行语义fill文本排版式换行只在行尾放不下的地方断开用于 Markdown 等场景indent/align/dedent控制缩进层级与对齐lineSuffix实现行尾注释的缓冲确保注释永远贴在所属行尾而不是被代码挤开ifBreak/indentIfBreak/conditionalGroup根据 group 是否断行选择不同内容其中conditionalGroup因嵌套时会指数级复杂化而被标注为最后手段。ArrayExpression的打印实现就是一个经典例子group([ [, indent([line, join([,, line], path.map(print, elements))]), line, ], ]);它是包裹着方括号和缩进内容的group只要任何子表达式被迫断行整个数组就会随之展开成多行——这正是文档数组会尽量单行、内含硬换行则必然展开行为背后的机制。整条链路解析 → Doc → 字符串可追溯至 src/main/core.js 中的coreFormat函数你也可以用仓库 Playground 的doc-explorer特殊 parser 直观观察 IR 的打印过程。选项哲学风格争论不该换个形式卷土重来既然要终结风格争论选项越多就越背离这一目标——争论只是从该用哪种风格变成该用哪些 Prettier 选项。正如 docs/option-philosophy.md 明确宣告的Prettier 因历史原因保留了少数选项但不会再增加新选项。文档承认少数选项有其合理动机--trailing-commaes5在无需转译的大多数环境中使用尾逗号函数尾逗号 ES2017 才加入--prose-wrap兼容各种特性各异的 Markdown 渲染器--html-whitespace-sensitivity应对 HTML 糟糕的空白规则--end-of-line方便团队把 CRLF 挡在 git 仓库之外--quote-props支撑 Google Closure Compiler 的高级用法。但另一些选项如--arrow-parens、--jsx-single-quote、--bracket-same-line、--no-bracket-spacing则被坦承为历史遗留物容易在团队中引发无谓的琐碎争论。文档明确格式化相关的选项请求将不再被接受请求保留输入格式如保留换行本质上也是变相的新选项同样不予受理只有在技术必要性如兼容性面前才可能破例。从 docs/options.md 可以看到这套克制的选项集的代表性成员printWidth默认 80表示希望的理想行长而非硬性上限与 ESLintmax-len语义不同、tabWidth默认 2、useTabs默认 false且遵循 SmartTabs——缩进用 tab、对齐仍用空格、semi默认 true关闭时仅在可能引发 ASI 失败的行首补分号、singleQuote默认 false且总是选择转义次数最少的引号风格。它们全部可以通过 CLI 覆盖或 API 配置但官方强烈建议通过配置文件固化以便 CLI、编辑器集成与其他工具读取同一套设置。落地实践从 CLI 到 pre-commit 钩子把为什么要用落到怎么用官方推荐在 docs/configuration.md配置、docs/editors.md编辑器与 docs/precommit.md提交前检查三份文档之间配合推进1. 命令行快速验证直接对文件或 stdin 运行 Prettier先看--check模式的差异再用--write落盘对混合类型目录建议加--ignore-unknown避免误伤不支持的文件。2. 配置文件固化选项在仓库根目录放置prettier.config.js或.prettierrc并通过.prettierignore声明无需格式化的路径。本仓库自身的 prettier.config.js 即是一个可复制的模板。3. 接入 pre-commit 钩子docs/precommit.md 提供了多种方案lint-staged配合 husky适合与 ESLint、Stylelint 等工具并存也支持git add --patch部分暂存npx mrm2 lint-staged可一键安装配置pretty-quick配合 simple-git-hooks专注于对变更/暂存文件做整文件格式化git-format-staged直接作用于 git 对象库中的对象保证提交中的变更永远被格式化、未暂存改动绝不会被误暂存、冲突时不覆盖工作区Lefthook多语言钩子管理器可并行跑多种工具的钩子stage_fixed: true会把 Prettier 改过的文件重新加入暂存Shell 脚本手写.git/hooks/pre-commit用git diff --cached --name-only --diff-filterACMR收集暂存文件、交给prettier --ignore-unknown --write再git add回暂存区。其中git-format-staged的-f prettier --ignore-unknown --stdin --stdin-filepath {}展示了 Prettier 通过 stdin 接受内容、配合--stdin-filepath推断解析器的能力这也是钩子只格式化暂存文件、不碰未暂存改动这一强保证得以成立的基础。结语一次投入永久摆脱风格争论回到官方文档的核心论点采纳 Prettier 的首要理由是终止无休止的风格争论而 Prettier 是唯一全自动、因此也是唯一能让风格指南零维护成本的方案。它让新人更快融入、让老手把心智留给真正的编码、让存量代码库一次清理到位并通过克制到冻结的选项集避免争论换个形式复活。其底层解析 AST → 生成 Doc 中间表示 → 按行宽智能断行的打印算法见 commands.md 与 src/main/core.js保证了这一切是全自动且可预测的。如果你正在为该不该引入 Prettier或如何让团队接受它发愁答案很简单先跑一次--check看看差异把它写进 pre-commit然后——停止争论跟随它的风格。【免费下载链接】prettierPrettier is an opinionated code formatter.项目地址: https://gitcode.com/gh_mirrors/pr/prettier创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →