尧图精选

Prettier 代码格式化完全指南:从配置到团队落地与常见问题排查

🕒 发布时间:2026/10/1 18:55:34 📁 来源:尧图网络
代码评审里最没有价值、却最容易引发争论的永远是格式问题。单引号还是双引号、对象末尾加不加逗号、箭头函数参数要不要括号——这些配置在技术圈吵了十年也没有标准答案。我见过一个前端新人在 PR 里被“顺手改一下格式”的评论淹没也见过一次着急上线的项目里核心逻辑的修改混进了大面积格式重排代码评审的人盯着 diff 看了半小时愣是没看出问题。后来团队统一引入 Prettier 做代码格式化这类问题才彻底终结。这篇文章把我这些年用 Prettier 的完整经验整理出来。从核心配置项到底层原理从 VS Code 到 IDEA 的集成配置从提交前自动格式化到 CI 检查再到网上经常有人问的“IDEA 里 Prettier 格式化失效”到底怎么排查都会讲到。不管你是刚接触代码格式化还是已经在团队里推广过一轮应该都有值得借鉴的地方。1. 先搞清楚Prettier 到底解决了什么问题1.1 代码风格之争一场没有赢家的口舌战先说一个很现实的问题代码格式化这件事看起来是小事实际每天都在消耗团队精力。我最早参与的一个项目团队约定用 Single Quote用 2 个空格缩进对象尾逗号要加。约定写在 wiki 里了但每个人的编辑器配置不一样有人用 VS Code有人用 WebStorm还有人用 Vim。结果每次提交的 diff 里都有大量“无意义改动”——不是这行缩进多了两个空格就是那行引号被自动改成了单引号。代码评审的人要在一堆格式噪音里找真正的逻辑变更效率极低。而且更麻烦的是这种问题不是靠“大家自觉”能解决的。人的注意力是有限的手写代码的时候很容易漏掉尾逗号或者一条语句太长随手就按了换行。就算你在评审里反复提醒下个迭代还是会出现同样的问题。所以后来我意识到格式约定不是靠人执行而是靠工具自动执行。这就是 Prettier 这类代码格式化工具存在的根本原因——把“如何排版”从人的脑子里抽离出来变成一条确定的、机器可执行规则。1.2 Prettier 的核心设计先解析再重新打印Prettier 的工作原理和大多数人想象的不太一样。它不是简单地做“查找替换”比如把双引号全改成单引号这种字符串级操作而是先把源码解析成抽象语法树AST然后丢掉原有的排版再按照一套固定规则把代码重新“打印”出来。你可以把它理解成**“先推倒再重建”**读代码、理解代码结构、然后用自己的排版逻辑重写一遍。这也是为什么 Prettier 格式化之后的结果非常统一——不管原来代码写成什么样只要 AST 一致输出就是一样的。这里有个很重要的设计思想Prettier 是“opinionated”的强主张式。它的作者团队故意只提供极少的配置项很多细节比如是否换行、操作符两侧空格都不给你选择余地。很多人刚用的时候会抱怨“为什么不让我自定义”但恰恰是这种“独裁”让格式化结果全局统一。你不需要在团队里开会讨论十种风格大家闭眼接受默认即可。1.3 能不能用 ESLint 或 IDE 自带格式化替代经常有人问我已经用了 ESLint能不配 Prettier 吗或者编辑器自带格式化那么好用为什么还要单独装一个工具我的回答是角色不一样不能互相替代。ESLint 的本质是代码质量检查它关心的是“代码里有没有 bug、有没有未使用的变量、有没有明显的反模式”。虽然它也包含一部分格式相关规则但那是它的副业不是主业。IDE 自带的格式化比如 IntelliJ 的 Reformat Code、VS Code 内置 formatter最强的地方是“适配这个 IDE 的默认审美”但不同 IDE 格式化结果不一样团队里只要有人用不同 IDEdiff 还是会乱。Prettier 的价值在于它是跨编辑器、跨语言、结果唯一的。同一份代码在任何机器上用同样配置跑 Prettier出来的字符级结果完全一致。这一点是 ESLint 和 IDE 自带格式化都做不到的。2. 配置项逐个拆解这些参数你真的理解了吗Prettier 配置项不多但每个都有讲究。下面我按类别拆开讲顺便把最容易误解的地方说清楚。2.1 行宽与缩进printWidth / tabWidth / useTabsprintWidth是 Prettier 最核心的配置默认值是 80含义是“代码行宽度达到多少时强制换行”。注意它不是一个强制的“最大行长”而是一个换行阈值——Prettier 会先尝试把代码保持在 80 列以内实在放不下才换行而且换行位置有它自己的算法。这个值建议保持默认。有些团队喜欢改成 100 或 120因为宽屏显示器确实能容纳更多代码。我的经验是如果你接手一个老项目先沿用项目已有风格如果是新项目从 80 开始不要一开始就调大。因为行宽越短强制换行越频繁diff 中换行噪音越多。tabWidth和useTabs配合使用。useTabs 默认为 false意思是“用空格模拟缩进”这时 tabWidth 决定一个缩进级别等于几个空格。绝大多数项目用 2 空格这也是 Prettier 的默认值。有个常见误区如果你设置 useTabs: true那么 tabWidth 就失去了意义。因为这时缩进是真实的 Tab 字符tabWidth 会影响的是你在代码里看到的“视觉宽度”但文件里存的确实是 Tab。我建议团队统一用空格而非 Tab因为空格在任意编辑器、任意 diff 工具里宽度都一样不会出现“我这边的 Tab 是 4 格你那边的 Tab 是 8 格”这种沟通成本。2.2 引号与分号semi / singleQuote / trailingComma这三个配置是团队里最常改的。semi控制是否在语句末尾加分号默认 true。很多从 Java/C# 转过来的团队比较习惯分号而相当一部分前端团队喜欢无分号风格semi: false。我的建议是新项目可以试试无分号但团队如果有人强烈不适应就尊重大多数人习惯。格式化工具的定位是“执行规则”而不是“制定规则”。singleQuote控制是否使用单引号默认 false即双引号。很多团队会改成 true因为 JavaScript 里字符串经常包含 HTML 属性、自然语言文本单引号写起来更简洁。注意一个细节singleQuote 只作用于代码中的字符串不影响 JSX 属性里的引号——那部分由jsxSingleQuote单独控制。trailingComma是最有故事的一个配置。它控制多行对象、数组、函数参数末尾是否加逗号。Prettier 2.x 默认是 es5对象/数组加、函数参数不加Prettier 3.0 开始默认改为 all能加的都加包括函数参数和函数调用。我强烈建议跟 Prettier 3.0 的默认值走统一用 all。因为尾逗号能大幅减少“最后一行加代码导致上一行被标记为变更”这类 diff 噪音。Git 的 diff 是按行比较的有尾逗号时在末尾新增一项不会碰完前面的行没有尾逗号时要在上一行补逗号这一行就会被标记修改diff 看起来就特别乱。2.3 括号与箭头函数bracketSpacing / arrowParens / bracketSameLinebracketSpacing控制对象字面量的花括号两侧是否加空格默认 true输出{ foo: bar }改成 false 会输出{foo: bar}。这个纯看审美但建议保持默认因为大多数代码风格指南都习惯括号内侧带空格。arrowParens控制箭头函数参数是否加括号默认 always即(x) x而不是x x。Prettier 2.0 之前默认是 avoid之后改成了 always。从 diff 稳定性角度讲“always”是更优的选择以后参数从 1 个变成 2 个不需要动原有的那行加括号。bracketSameLine在 2.4 版本之前叫jsxBracketSameLine控制 JSX/HTML 标签的是否跟随最后一个属性换行。默认 false 会把放在新行。这里我建议保持默认因为 Prettier 团队调研过当属性很多时把单独放一行diff 的可读性更好。这个配置也比较新老项目升级时要注意旧配置名的迁移。2.4 换行与版本差异endOfLine / proseWrap / 3.0 注意事项endOfLine控制换行符类型默认在 Prettier 3.0 是 lf。在 2.x 时代默认是 auto导致同一个项目在 Windows 上可能被格式化成 CRLF在 macOS/Linux 上被格式化成 LF提交到 git 里就会看到“整个文件都红了”。建议显式配置为 lfWindows 开发者配合 Git 的core.autocrlf设置即可。proseWrap影响 Markdown 和文本类文件的换行方式默认 preserve意思是“保持你原来的换行不要动”。如果你交给 Prettier 格式化 Markdown 时出现“整段被合并/重排”的情况多半是这个值被改过。建议就保持 preservePrettier 管好代码文件就够了Markdown 里的手动换行习惯不是它该管的。版本差异方面Prettier 3.0 把trailingComma 默认值从 es5 改成 all、endOfLine 默认值从 auto 改成 lf同时要求Node.js 14。这些看起来是小变化但在老项目升级时会有不少格式 diff。我的建议是升级 Prettier 主版本时单独提一个 commit 跑一遍全量格式化不要和其他功能改动混在一起。3. 从安装到落地一套可以直接抄走的项目配置3.1 安装依赖与生成配置文件在项目里装 Prettier第一步是把包作为开发依赖安装npm i -D prettier然后创建配置文件.prettierrc.json。这是我的标准配置可以直接抄{ printWidth: 80, tabWidth: 2, useTabs: false, semi: true, singleQuote: true, quoteProps: as-needed, jsxSingleQuote: false, trailingComma: all, bracketSpacing: true, bracketSameLine: false, arrowParens: always, endOfLine: lf, htmlWhitespaceSensitivity: css, proseWrap: preserve }配置文件支持多种格式.prettierrcJSON 或 YAML、.prettierrc.json、prettier.config.js、.prettierrc.cjs也可以在package.json里加prettier字段。我习惯用.prettierrc.json因为它简单、不会被执行也不会因为注释语法在不同环境里有差异。配置好之后在package.json里加两个脚本{ scripts: { format: prettier --write ., format:check: prettier --check . } }--write会直接改写文件--check只检查不改写用于 CI。注意prettier --write .会递归格式化当前目录下的所有支持文件前提是你的.prettierignore把该忽略的目录都排除了。3.2 编辑器自动化VS Code 的 Format On Save本地开发时最舒服的方式是保存文件时自动格式化。VS Code 需要先安装插件Prettier - Code formatter作者是 Prettier 团队插件 ID 是esbenp.prettier-vscode。然后在项目根目录创建.vscode/settings.json把格式化的默认工具指到 Prettier并开启保存时格式化{ editor.defaultFormatter: esbenp.prettier-vscode, editor.formatOnSave: true, prettier.requireConfig: true }prettier.requireConfig的意思是“只有项目里有 Prettier 配置文件时才启用”防止你在一个没有配过 Prettier 的项目里无意间格式化出风格迥异的代码。这个设置对团队协作尤其重要因为每个人的编辑器偏好不同通过.vscode/settings.json提交到仓库整个团队的编辑器行为就统一了。3.3 提交前自动格式化husky lint-staged保存时格式化解决了个人开发环境的问题但没法保证每个成员都配置正确。有人不装插件、有人跳过保存、有人临时改了一行就提交了。这时候需要最后一个兜底环节——git 提交前自动格式化。我用的是husky加lint-staged。lint-staged的作用是只对“已经暂存git add 过的文件”执行格式化命令这样不会把整个项目的文件都扫一遍速度很快。安装并初始化npm i -D husky lint-staged npx husky init执行npx husky init会在项目里生成.husky/pre-commit文件内容修改为npx lint-staged然后在package.json里配置 lint-staged{ lint-staged: { **/*.{js,jsx,ts,tsx,json,css,scss,less,html,md,vue}: [ prettier --write ] } }当开发者执行git commit时pre-commit 钩子会把暂存区里的代码先跑一遍prettier --write。如果格式化后有改动这些改动会被重新加回暂存区然后提交。这样即使某个人在编辑器里没开 Format On Save提交时也会被强制统一。3.4 在 CI 里守住最后一道防线pre-commit 钩子也有被绕过的办法比如git commit --no-verify。为了防止“漏网之鱼”在合并请求里污染 main 分支建议在 CI 里加一步检查。GitHub Actions 的工作流文件可以这样写name: CI on: pull_request: push: branches: [main] jobs: format: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - uses: actions/setup-nodev4 with: node-version: 20 - run: npm ci - run: npm run format:check也就是执行prettier --check .只要有任何文件格式不一致CI 就失败。这能保证仓库主干上的代码永远处于“已格式化”状态。这三层编辑器自动、提交钩子、CI 检查互相兜底基本可以做到团队零配置接入。4. 重点排查IDEA 中 Prettier 格式化失效的真相“IDEA 代码格式化失效”是在开发者社区里高频出现的问题。这里单独用一章说清楚。4.1 失效的典型表现与排查路径先对照现象看看你属于哪一类现象最可能的原因保存文件后代码没有变化没有勾选 On save或 Prettier 包路径未配置保存后有格式化但风格不是 Prettier走的是 IDEA 自带格式化器不是 Prettier手动 CtrlAltL 格式化后风格不对Reformat Code 调用的不是 Prettier某些文件格式化生效某些文件不生效Run for files 的文件类型匹配范围没有覆盖该类型报错提示找不到 Node 或 Prettier 模块IDEA 的 Node 解释器或 Prettier package 路径配置错误需要明确的一点是IDEA/WebStorm 的CtrlAltLReformat Code是 IDEA 自带的格式化功能和 Prettier 插件是两套完全独立的机制。很多人以为装了 Prettier 插件再按这个快捷键就会走 Prettier实际上不一定。4.2 根因一CtrlAltL 调用的根本不是 Prettier这是“失效”最常见的误解。即使安装了 Prettier 插件、即使正确配置了包路径按 CtrlAltL 执行的仍然可能是 IDEA 的内置格式化风格自然对不上。正确做法有两个任选其一第一在Settings Tools Prettier老版本在Settings Languages Frameworks Prettier里勾选“Use Prettier as default code formatter”。勾选后CtrlAltL 就会走 Prettier。第二使用 Prettier 插件自己的动作“Prettier: Reformat Code”在 Keymap 里给它分配一个快捷键。这样就能保留一个独立快捷键专用于 Prettier不会被 IDEA 默认格式化占位。插件和 IDE 版本有差异菜单位置可能在 Tools 或 Languages Frameworks 之间变化找不到的直接在设置搜索框搜 “Prettier”。4.3 根因二Prettier 包路径和 Node 环境问题IDEA 里 Prettier 插件不是内置了 Prettier 引擎而是需要加载项目里的prettier包。如果 Prettier package 这一栏是空的或者指到了一个没有安装 Prettier 的目录插件就会静默失效——保存时什么都不做也不报错。排查时先确认三件事项目里确实执行过npm i -D prettiernode_modules/prettier存在。Settings Tools Prettier 里的Prettier package选择了项目的node_modules/prettier路径。Node 解释器设置正确版本不低于 14Prettier 3.x 的要求。另外还要注意.editorconfig 的干扰。如果你在项目里放了.editorconfig且里面设置了indent_size或indent_style旧版 Prettier 在某些情况下会被 EditorConfig 覆盖缩进配置导致结果和prettier --write不一致。解决方式是把.editorconfig里的缩进设置调成和 Prettier 配置一致或者确保 Prettier 版本较新新版本对 EditorConfig 不再默认读取。4.4 一套稳妥的 IDEA 集成配置方案下面这套是我在 WebStorm 和 IntelliJ IDEA 里实测稳定的配置流程在插件市场安装Prettier插件新版本 IDEA 可能自带装好之后重启 IDE。确认项目本地安装了 prettier 依赖npm i -D prettier。打开 Settings Tools Prettier在 Prettier package 处选择node_modules/prettier。勾选On save保存时自动格式化。勾选Use Prettier as default code formatter接管内置格式化。检查Run for files的默认匹配模式确认覆盖你需要格式化的扩展名**/*.{js,jsx,ts,tsx,vue,json,css,scss,html,md,yml,yaml,graphql,markdown}。打开一个 JS 文件故意写成双引号、缺尾逗号保存看是否被格式化为配置风格。这套配置走完后“格式化失效”的绝大多数场景都能解决。如果仍然不发格式化再看 IDEA 日志Help Log in Explorer里是否有 Prettier 相关的异常。5. 与 ESLint 分工以及老项目迁移的经验5.1 Prettier 管格式化ESLint 管质量新团队经常会陷入一个误区在 ESLint 里配置一大堆格式规则比如quotes、semi、indent试图用 ESLint 同时完成代码风格和质量检查。这类做法最大的问题是规则冲突和职责混乱ESLint 的格式规则和 Prettier 的格式化规则经常互相打架今天改了 ESLint 配置明天 Prettier 格式化完又违反了。我的原则很简单ESLint 只管“代码有没有问题”Prettier 只管“代码好不好看”。ESLint 里面no-unused-vars、no-constant-binary-expression这类规则属于质量检查保留quotes、semi、indent这类纯排版规则全部交给 Prettier。5.2 规则冲突的标准解法eslint-config-prettier如果你已经在 ESLint 里配了很多格式规则逐个删太费劲。标准解法是装上eslint-config-prettier它会把所有和 Prettier 可能冲突的规则一次性关掉。npm i -D eslint-config-prettier然后在 ESLint 配置文件的extends数组最后一项加上{ extends: [ eslint:recommended, some-other-config, prettier ] }用它之后ESLint 和 Prettier 的规则冲突就消失了。这里有个取舍要讲社区里还有一种做法是eslint-plugin-prettier把 Prettier 当成一个 ESLint 规则来跑配合plugin:prettier/recommended一步到位。我不推荐这种做法的原因有两个一是eslint --fix里再跑 Prettier速度明显变慢二是职责变混以后排查问题时要同时考虑两套工具。我更偏好“pre-commit 里跑prettier --write ESLint 做质量检查”这种两步方案。5.3 .prettierignore哪些文件不该格式化和.gitignore类似Prettier 也支持.prettierignore文件来控制忽略范围。很多人觉得“先跑一下才知道哪些不该格式化”实际上初始化时就把该忽略的都列上是经验之谈。我的.prettierignore模板node_modules dist build coverage public package-lock.json pnpm-lock.yaml yarn.lock *.min.js *.min.css注意几个细节package-lock.json这类锁文件虽然 Prettier 默认会忽略一部分但显式写出来更稳妥*.min.js这类压缩产物绝对不能格式化否则不但体积暴增还可能在压缩代码里引入字符集问题如果项目里有接口 mock 数据、基线截图之类的文件也要考虑加进去。5.4 老项目全量迁移的三个经验老项目接入 Prettier 时最纠结的问题是“全量格式化会不会把 git 历史搞乱”。我的经验是按三步走第一步先把配置定下来跑一次全量格式化单独提交一个 commit。commit message 写成refactor: apply prettier formatting这种一眼能看出的格式。第二步配置 git blame 忽略该 commit防止以后查历史时整个文件都算格式化 commit 的锅。在项目根目录创建一个.git-blame-ignore-revs文件写上格式化那次提交的 hash# apply prettier formatting a1b2c3d4e5f6...然后执行git blame --ignore-revs-file .git-blame-ignore-revs src/xxx.jsGitHub 也支持在仓库设置里配置.git-blame-ignore-revs配置后网页版的 blame 视图会自动跳过那次提交。第三步不要在功能分支里混着跑全量格式化。格式化会产生大量 diff如果和功能改动混在一起一旦出现回归定位问题的成本极高。正确姿势是先在一个单独的分支做全量格式化并合入主干其他分支稍后 rebase 到主干上。6. 常见问题速查表与收尾6.1 症状-原因-处理对照表症状原因处理方式不同电脑跑出的结果不一致Prettier 版本不一致或配置未统一锁定 prettier 版本配置文件提交到仓库保存时没有格式化编辑器 Format On Save 未开启或格式化工具指向错误检查编辑器配置确认 defaultFormatter 为 PrettierIDEA 保存无反应On save 未勾选 / Prettier package 路径为空Settings Tools Prettier配置包路径并勾选 On save格式化后和 ESLint 报错冲突两套工具规则重叠使用 eslint-config-prettier 关闭 ESLint 格式规则Markdown 表格被重排打乱proseWrap 被改成其他值设置proseWrap: preserveHTML 缩进异常htmlWhitespaceSensitivity 值不合适保持默认 css如有需求可单独调整升级 Prettier 3.0 后大量 diff默认值变化trailingComma、endOfLine单独提交格式化的 commit并用 git blame 忽略格式化超大文件很慢全量格式化所有历史文件只格式化改动文件lint-staged6.2 最后分享几个容易忽略的细节最后说三个我踩过坑之后的经验。第一不要把 prettier 版本范围写成^。如果你在 package.json 里写prettier: ^3.0.5那么同事在两个月后执行npm install时可能装到 3.x 的另一个次版本。Prettier 在版本迭代中偶尔会有格式化结果微调这会导致不同人本地格式化结果不一致CI 又恰好卡在这一处。锁定精确版本比如prettier: 3.0.5能省掉很多莫名其妙的“我这边过你那边不过”。第二不要用prettier --write src这种目录级命令一刀切执行。除非你确认哪些文件该格式化。更安全的姿势是配合 lint-staged 或.prettierignore做好排除否则很容易把不该动的生成文件卷进来。第三遇到格式化结果“不稳定”的时候先怀疑版本再怀疑配置。Prettier 的设计目标就是让结果在相同配置下完全可预测如果两个环境结果不同优先对比 prettier 版本和配置文件而不是找插件问题。按照我这套流程从个人开发环境到团队协作规范Prettier 能真正把“代码格式”这件事变成完全不用人操心的流水线。配置不复杂收益却立竿见影值得在每个项目里落地。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →