面试题手册

梳理高频技术问题,帮助你按主题复习和查漏补缺。

前端阅读 02026年5月30日 10:11

Prettier 支持哪些语言和文件类型?

Prettier 原生支持 JavaScript、TypeScript、JSX、TSX、CSS、SCSS、Less、HTML、Vue、Angular、JSON、YAML、Markdown、MDX、GraphQL 等常见前端和文档格式。Java、PHP、Ruby、XML 等也可以通过插件或社区解析器支持。判断能不能格式化,关键看 Prettier 是否有对应 parser。追问Prettier 原生支持哪些文件?常见有 .js、.jsx、.ts、.tsx、.css、.scss、.less、.html、.vue、.json、.yaml、.md、.mdx、.graphql。插件支持和原生支持有什么区别?原生支持开箱即用;插件支持需要额外安装包,团队里要统一依赖版本,否则 CI 和本地结果可能不一致。Prettier 怎么判断用哪个解析器?通常根据扩展名自动选择 parser。识别不了时,可以用 overrides 指定 parser。写段代码{"overrides":[{"files":"*.vue","options":{"parser":"vue"}}]}
前端阅读 05月28日 07:28

Prettier 与其他代码格式化工具有什么区别?如何选择?

Prettier 和 ESLint 有什么本质区别?Prettier 是代码格式化工具,ESLint 是代码质量检查工具,二者不是替代关系而是互补关系。核心区别在于工作原理:Prettier 将代码解析为 AST(抽象语法树),然后按照自己的规则重新输出,保证同样的输入永远得到同样的输出;ESLint 则基于规则引擎逐行扫描代码,检测潜在的错误和反模式。实际项目中标准做法是两者结合:用 eslint-config-prettier 关闭 ESLint 中与格式化重叠的规则,让 Prettier 完全负责格式化(缩进、换行、引号风格),ESLint 专注代码质量(未使用变量、潜在 bug、最佳实践)。// .eslintrc.json{ "extends": ["eslint:recommended", "prettier"], "plugins": ["prettier"]}Prettier 相比 Beautify、Standard.js 的优势在哪?vs Beautify: Beautify 基于正则匹配做格式化,不具备 AST 解析能力,对复杂语法结构(如嵌套的三元表达式、链式调用)的格式化效果差,且输出不确定——同一份代码多次格式化可能产生不同结果。Prettier 基于 AST 重新打印代码,输出完全确定性,这是团队协作的基础。vs Standard.js: Standard.js 是"零配置"的代名词,但它不允许任何自定义——分号必须有或必须没有,没有中间地带。Prettier 同样开箱即用,但保留了少量关键配置(单引号/双引号、分号、行宽等),适合需要一定灵活性的团队。| 维度 | Prettier | Beautify | Standard.js ||------|----------|----------|-------------|| 解析方式 | AST | 正则 | AST || 输出确定性 | 完全确定 | 不确定 | 完全确定 || 可配置性 | 少量关键选项 | 丰富 | 几乎为零 || 多语言支持 | JS/TS/CSS/HTML/JSON/MD | JS/CSS/HTML | JS/TS |Biome 等新一代工具会取代 Prettier 吗?2026 年 Biome 成为最值得关注的替代方案。它用 Rust 编写,将格式化和 lint 合并为一个工具,在大型 monorepo 中性能优势显著:10,000+ 文件的项目,格式化+检查不到 200ms,而 ESLint+Prettier 组合需要近 12 秒。但 Prettier 短期内不会被取代,原因有三:生态成熟度: Prettier 拥有大量编辑器插件、预提交钩子、CI 集成方案,Biome 生态仍在追赶插件体系: Prettier 支持插件格式化额外语言(如 Java、Ruby、PHP),Biome 目前语言覆盖有限迁移成本: 已有项目的 .prettierrc 配置和格式化基线,切换工具意味着大量 diff选择建议: 新项目可以尝试 Biome,享受性能提升和简化配置;已有项目不必急于迁移,等 Biome 生态更成熟再说。Prettier 的 AST 重打印机制是什么意思?这是理解 Prettier 行为的关键。Prettier 的工作流程:解析(Parse): 将源代码解析为 AST遍历(Traverse): 遍历 AST 节点打印(Print): 根据行宽限制和自身规则重新输出代码这意味着 Prettier 不是"调整"你的代码,而是"重新生成"你的代码。你写的空行、多余括号、手动对齐——大部分都会被丢弃重写。这也是为什么 Prettier 配置选项少:它不是逐条规则控制,而是整体重打印,只暴露行宽、缩进等顶层参数。这种设计牺牲了灵活性,换来了确定性。实际项目中怎么配置 Prettier + ESLint?完整的工程化配置分三步:第一步:安装依赖npm install -D prettier eslint eslint-config-prettier eslint-plugin-prettier第二步:配置文件// .prettierrc{ "semi": true, "singleQuote": true, "printWidth": 80, "trailingComma": "es5"}// .eslintrc.json{ "extends": ["eslint:recommended", "plugin:prettier/recommended"], "env": { "es2024": true, "node": true }}plugin:prettier/recommended 做了三件事:加载 eslint-plugin-prettier(把 Prettier 规则作为 ESLint 规则运行)、加载 eslint-config-prettier(关闭 ESLint 格式化相关规则)、设置 prettier/prettier 为 error 级别。第三步:编辑器集成// .vscode/settings.json{ "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll.eslint": "explicit" }}保存时先 Prettier 格式化,再 ESLint 自动修复,分工明确不冲突。第四步:Git 钩子自动化npm install -D husky lint-stagednpx husky initecho "npx lint-staged" > .husky/pre-commit// package.json{ "lint-staged": { "*.{js,ts}": ["eslint --fix", "prettier --write"], "*.{css,html,json,md}": ["prettier --write"] }}提交时自动格式化和检查,不合格的代码进不了仓库。Prettier 有哪些已知局限?配置不够灵活: 行宽以内无法手动换行,printWidth: 80 时超过 80 字符的链式调用会被强制换行,即使你手动排列得更易读。这是"确定性"的代价——不允许个人偏好覆盖工具判断。大项目性能瓶颈: Prettier 是单线程的,超大型项目全量格式化耗时较长。应对方式是用 lint-staged 只格式化变更文件,或引入缓存。版本升级可能产生 diff: Prettier 的格式化结果在不同大版本间可能有差异,团队必须锁定版本号,升级时全量格式化会产生大量无意义 diff。面试追问:什么时候不该用 Prettier?三种场景下 Prettier 不是最佳选择:遗留大型项目: 全量格式化会产生数千行 diff,干扰 code review,建议渐进式引入(只格式化新文件或变更文件)需要精细控制格式的场景: 如代码生成器输出、教学材料中特意安排的缩进,Prettier 的重打印会破坏这些刻意格式纯 Python 项目: Python 有 Black,设计理念与 Prettier 一致但针对 Python 语法优化,混用 Prettier 反而增加复杂度
前端阅读 05月28日 07:26

如何在 CI/CD 中集成 Prettier 做代码格式检查?

为什么要用 Prettier 拦截代码格式问题代码格式不一致是团队协作中最容易引发无意义争论的问题。Prettier 通过"零配置强制统一"的思路消除了这类争议,但仅靠开发者自觉运行 Prettier 并不可靠——有人会忘记格式化,有人会选择性忽略。把 Prettier 检查嵌入 CI/CD 流水线,是保证代码库格式一致性的最后防线。推荐的两层防护策略:本地 Git Hook 做即时拦截 + CI 流水线做兜底检查。前者让开发者在提交前就能发现问题,后者防止绕过 Hook 的代码进入主分支。本地拦截:Git Hooks 配置Husky + lint-staged 方案这是目前最主流的方案,lint-staged 的核心优势是只格式化本次提交涉及的文件,不会全量扫描,提交速度有保障。安装依赖 npm install --save-dev husky lint-staged prettier npx husky install npm pkg set scripts.prepare="husky install"配置 lint-staged在 package.json 中添加: { "lint-staged": { "*.{js,jsx,ts,tsx}": [ "prettier --write" ], "*.{json,css,scss,md}": [ "prettier --write" ] } }分开配置的好处是后续可以为 JS/TS 文件加入 ESLint 检查,而不影响纯样式或文档文件。创建 pre-commit Hook npx husky add .husky/pre-commit "npx lint-staged"常见坑:Husky 不生效未执行 husky install:克隆仓库后需要手动运行一次 npm preparecorehooks 被覆盖:某些工具(如 Gerrit)会修改 Git hooks 路径,检查 git config core.hooksPathlint-staged 卡住:文件路径含空格或中文时需要用引号包裹 glob 模式CI 流水线集成GitHub Actions创建 .github/workflows/prettier.yml:name: Prettier Checkon: push: branches: [main] pull_request: branches: [main]jobs: prettier: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 - run: npm ci - run: npx prettier --check "src/**/*.{js,jsx,ts,tsx,json,css,scss,md}"关键细节:用 npm ci 而非 npm install,前者严格按照 lock 文件安装,CI 环境更稳定--check 模式只检查不修改,符合 CI "只读" 原则缩小 glob 范围到 src/ 目录,避免扫描 node_modules 或构建产物如果希望 PR 中直接看到哪些文件格式不对,可以用 --list-different 替代 --check,它会列出有问题的文件名,输出更直观:- run: npx prettier --list-different "src/**/*.{js,jsx,ts,tsx,json,css,scss,md}"GitLab CI在 .gitlab-ci.yml 中添加:prettier: stage: test image: node:20-alpine script: - npm ci - npx prettier --check "src/**/*.{js,jsx,ts,tsx,json,css,scss,md}" only: - merge_requests - main cache: key: ${CI_COMMIT_REF_SLUG} paths: - node_modules/用 node:20-alpine 镜像比完整 Node 镜像小 5 倍以上,流水线启动更快。加上 cache 配置避免每次都全量安装依赖。如果想在 GitLab 的 Code Quality 报告中展示 Prettier 错误,可以使用 @studiometa/prettier-formatter-gitlab 将输出转为 GitLab 可识别的格式。Jenkins在 Jenkinsfile 中添加阶段:stage('Format Check') { steps { sh 'npm ci' sh 'npx prettier --check "src/**/*.{js,jsx,ts,tsx}"' }}Bitbucket Pipelines在 bitbucket-pipelines.yml 中添加:pipelines: pull-requests: '**': - step: name: Prettier Check image: node:20-alpine script: - npm ci - npx prettier --check "src/**/*.{js,jsx,ts,tsx,json,css,scss,md}"Prettier 配置文件示例CI 检查的准确性依赖项目中有明确的 Prettier 配置。创建 .prettierrc:{ "semi": true, "singleQuote": true, "trailingComma": "es5", "printWidth": 100, "tabWidth": 2}同时创建 .prettierignore 排除不需要检查的内容:node_modulesdistbuildcoverage*.min.jspackage-lock.json配置必须在本地和 CI 之间保持一致——这也是为什么 Prettier 要作为 devDependencies 安装而非全局安装,npm ci 会确保 CI 环境拿到和本地完全相同的版本。Prettier 与 ESLint 的协作Prettier 只管格式,ESLint 管代码质量,两者配合才是完整方案。核心原则是用 eslint-config-prettier 关闭 ESLint 中与 Prettier 冲突的规则:npm install --save-dev eslint-config-prettier在 .eslintrc.js 中:module.exports = { extends: [ 'eslint:recommended', 'prettier' // 必须放在最后,覆盖前面的格式相关规则 ]}CI 中可以合并为一条检查:script: - npm ci - npx eslint "src/**/*.{js,ts}" - npx prettier --check "src/**/*.{js,ts,json,css,md}"Monorepo 场景的优化策略在 Turborepo 或 Nx 管理的 monorepo 中,全量 npm ci + 全局 Prettier check 会非常慢。两个优化方向:用 Turborepo 的 filter 定位变更包: npx turbo run format:check --filter=...[HEAD^]只检查本次提交影响到的包。用 changesets 圈定范围:在 CI 中先用 git diff 找出变更的包目录,再对对应目录执行 Prettier check。Prettier 的 --cache 选项(Prettier 3.1+ 支持):只检查未缓存的文件,对大型仓库效果显著: npx prettier --check --cache "src/**/*.{js,ts}"缓存默认写入 node_modules/.cache/prettier,CI 中记得把这个目录加入缓存配置。CI 检查失败怎么办当 CI 报告格式不一致时,最快的修复方式是在本地执行:npx prettier --write "src/**/*.{js,jsx,ts,tsx,json,css,scss,md}"如果频繁出现格式不一致,排查以下几点:Prettier 版本不一致:检查 package.json 中的版本,确保本地和 CI 的 npm ci 安装的是同一个版本编辑器格式化插件冲突:VS Code 中可能同时有多个格式化扩展在生效,在设置中指定 Prettier 为默认格式化器.editorconfig 与 .prettierrc 冲突:两者同时存在时 Prettier 优先,但建议统一到 .prettierrc 中管理核心要点总结本地 Git Hook 做即时反馈,CI 流水线做兜底保障,两者缺一不可--check 模式用于 CI,--write 模式用于本地修复,不要在 CI 中用 --write用 npm ci 代替 npm install 保证依赖版本一致性Prettier 与 ESLint 配合时,eslint-config-prettier 必须放在 extends 最后Monorepo 项目用 filter 或 --cache 缩小检查范围,避免全量扫描拖慢流水线
前端阅读 05月28日 07:26

Prettier 命令行工具有哪些常用命令和选项?

Prettier 命令行工具有哪些常用命令和选项?Prettier 的命令行工具是日常开发中格式化代码的核心手段,掌握常用命令和关键选项不仅能提升开发效率,也是前端工程化面试中的高频考点。核心命令格式化文件:--write--write 是最常用的选项,直接修改文件为格式化后的内容:# 格式化单个文件npx prettier --write src/index.ts# 格式化整个项目npx prettier --write .面试追问:--write 会先写入临时文件再原子替换原文件,避免写入中断导致文件损坏。检查格式:--check--check 只检查文件是否符合 Prettier 格式,不修改文件。文件不合规时退出码为 1,因此广泛用于 CI 流水线:npx prettier --check "src/**/*.{js,ts}"# 在 CI 中使用npx prettier --check . || echo "存在未格式化的文件"列出差异文件:--list-different--list-different(简写 -l)只输出格式不一致的文件路径,不输出格式化内容,适合脚本处理:npx prettier --list-different "src/**/*.js"与 --check 的区别:--check 会输出详细的人类可读信息,--list-different 只输出文件路径,更便于后续管道处理。查看差异:--diff--diff 输出格式化前后的 diff 对比,方便在不修改文件的前提下预览变更:npx prettier --diff src/app.ts配置与忽略指定配置文件:--config默认 Prettier 会沿目录向上查找 .prettierrc 等配置文件,使用 --config 可指定自定义配置:npx prettier --config .prettierrc.staging.json --write src/查找配置路径:--find-config-path输出给定文件实际使用的配置文件路径,用于排查配置生效问题:npx prettier --find-config-path src/index.ts# 输出: /project/.prettierrc忽略文件:--ignore-path默认使用 .prettierignore,可通过 --ignore-path 指定自定义忽略文件:npx prettier --ignore-path .gitignore --write .将 .gitignore 复用为忽略规则是一个实用技巧。忽略未知文件类型:--ignore-unknown格式化整个项目时,遇到 Prettier 不支持的文件类型默认会报错,加上此选项会自动跳过:npx prettier --write --ignore-unknown .缓存与性能启用缓存:--cache大型项目格式化耗时较长,--cache 通过缓存未变更文件的格式化结果显著提升速度:npx prettier --write --cache "src/**/*.ts"缓存位置:--cache-location指定缓存文件的存储路径:npx prettier --write --cache --cache-location .prettiercache src/缓存策略:--cache-strategy支持两种策略:metadata(默认):根据文件修改时间判断,速度快但不够精确content:根据文件内容哈希判断,更精确但稍慢npx prettier --write --cache --cache-strategy content src/输出控制输出到标准输出不加 --write 时,Prettier 将格式化结果输出到 stdout,不修改原文件:npx prettier src/index.ts指定输出目录:--out-dir将格式化结果写入指定目录而非原文件,适合生成格式化副本:npx prettier "src/**/*.js" --out-dir formatted/标准输入:--stdin-filepath从标准输入读取代码时,Prettier 无法判断文件类型,通过此选项指定虚拟路径:echo "const x=1" | npx prettier --stdin-filepath index.ts这在编辑器集成和管道场景中非常关键。与工程化工具集成在 package.json 中配置脚本{ "scripts": { "format": "prettier --write "src/**/*.{js,ts,json,css,md}"", "format:check": "prettier --check "src/**/*.{js,ts,json,css,md}"", "format:all": "prettier --write --ignore-unknown ." }}配合 lint-staged 只格式化暂存文件{ "lint-staged": { "*.{js,ts,css,md}": "prettier --write" }}这样配合 husky 的 pre-commit 钩子,每次提交只格式化本次变更的文件,避免全量格式化带来的提交噪音。在 CI 中强制格式检查- name: Check formatting run: npx prettier --check .--check 在文件不合规时返回退出码 1,CI 流水线会因此失败,确保仓库中不会混入未格式化的代码。调试命令调试检查:--debug-check格式化文件并检查格式化是否改变了 AST,用于排查 Prettier 自身的 bug。不能与 --write 同时使用:npx prettier --debug-check src/index.ts查看帮助与版本npx prettier --helpnpx prettier --versionPrettier 命令行工具在日常开发中主要用于格式化和检查,在工程化体系中则通过 --check 与 CI 集成、通过 --list-different 与 lint-staged 配合,理解每个命令的应用场景比记住参数更重要。
前端阅读 05月28日 07:25

如何在 Monorepo 项目中配置和使用 Prettier?

核心答案在 Monorepo 中配置 Prettier,关键是统一配置 + 分包覆盖 + 工具链集成三步走:根目录放一份基础 .prettierrc 作为全局基准,通过共享配置包 @org/prettier-config 让各子项目继承,再用 overrides 按包定制差异规则,最后配合 Husky + lint-staged 在提交时自动格式化、Turborepo/Nx 在 CI 层做缓存检查。根目录统一配置最简单的方式是在 monorepo 根目录创建 .prettierrc:{ "semi": true, "singleQuote": true, "tabWidth": 2, "trailingComma": "es5", "printWidth": 80}Prettier 会从文件所在目录向上查找配置,子包如果自己没有 .prettierrc,就自动继承根目录的规则。这意味着只要根目录配置到位,大部分子包无需额外配置。需要注意的是,如果子包自己也有 .prettierrc,它会完全覆盖根配置而不是合并。所以除非有必要,不要在子包里单独放配置文件。共享配置包当团队规模较大或 monorepo 包含多个独立发布的库时,推荐把 Prettier 配置抽成 npm 包:// packages/prettier-config/index.jsmodule.exports = { semi: true, singleQuote: true, tabWidth: 2, trailingComma: "es5", printWidth: 80, bracketSpacing: true, arrowParens: "always",};// packages/prettier-config/package.json{ "name": "@my-org/prettier-config", "version": "1.0.0", "main": "index.js"}在各子包中引用:{ "prettier": "@my-org/prettier-config"}共享配置包的优势在于版本可控——改一处发布新版本,所有依赖它的子包 npm update 即可同步。对于使用 pnpm workspace 的项目,直接用 workspace:* 协议引用,无需发布到外部 registry。分包差异化配置(overrides)有些子包需要不同的格式化规则,比如 UI 库希望更宽的 printWidth,而后端服务保持 80 列。用 overrides 字段实现:{ "semi": true, "singleQuote": true, "printWidth": 80, "overrides": [ { "files": "packages/ui/**/*", "options": { "printWidth": 100 } }, { "files": "packages/server/**/*", "options": { "printWidth": 80 } }, { "files": "packages/docs/**/*.md", "options": { "proseWrap": "always", "printWidth": 90 } } ]}overrides 是在根配置基础上增量覆盖,不会丢失未显式指定的规则。这比在每个子包单独放 .prettierrc 更容易维护。.prettierignore 配置很多教程忽略了 .prettierignore,但它在 monorepo 中非常关键。典型的忽略规则:node_modulesdistbuildcoverage.next.turbo*.min.js*.min.csspnpm-lock.yamlpackage-lock.json不配 .prettierignore 会导致 prettier --write 扫描 node_modules 和构建产物,既浪费时间又可能报错。尤其在 monorepo 中,子包的 dist 目录层级深,手动排除不现实,需要用通配符一次搞定。与 ESLint 的冲突解决Prettier 和 ESLint 同时存在时,格式化规则会冲突。比如 ESLint 要求尾逗号,Prettier 又删掉尾逗号,来回打架。解决方案分两步:第一步:安装 eslint-config-prettier,它关闭所有与 Prettier 冲突的 ESLint 规则:pnpm add -wD eslint-config-prettier// .eslintrc.jsmodule.exports = { extends: [ "eslint:recommended", // 其他配置... "prettier" // 必须放最后,覆盖前面的格式化规则 ]};第二步(可选):如果想在 ESLint 中实时报告格式问题,安装 eslint-plugin-prettier:pnpm add -wD eslint-plugin-prettiermodule.exports = { plugins: ["prettier"], rules: { "prettier/prettier": "error" }};不过在 monorepo 中,更推荐的做法是分离职责:ESLint 只管代码质量,Prettier 只管格式,不要把 Prettier 嵌入 ESLint。这样运行更快,调试也更清晰。Husky + lint-staged 自动格式化提交时自动格式化是 monorepo 的标配实践:pnpm add -wD husky lint-stagedpnpm exec husky init// package.json{ "lint-staged": { "*.{js,jsx,ts,tsx}": ["prettier --write"], "*.{json,css,md}": ["prettier --write"] }}# .husky/pre-commitpnpm exec lint-staged这样每次 git commit 只会格式化暂存区的文件,而不是整个项目。对于 monorepo 来说,增量处理比全量扫描快得多。如果使用 pnpm workspace,可以把 lint-staged 配置放在根目录,它会自动根据修改文件的路径匹配对应规则。Turborepo 集成Turborepo 的缓存机制能避免重复格式化检查:// turbo.json{ "pipeline": { "format": { "outputs": [] }, "format:check": { "outputs": [] } }}// 根 package.json{ "scripts": { "format": "prettier --write .", "format:check": "prettier --check ." }}outputs 设为空数组是因为格式化不产生构建产物,Turborepo 只需要根据输入文件的变化判断是否需要重新执行。实际项目中,format:check 通常放在 CI 里,而 format 在本地开发时使用。Turborepo 会缓存未变更文件的结果,二次运行几乎零耗时。Nx 集成Nx 对 Prettier 有专门的 executor 支持:{ "targets": { "format": { "executor": "@nx/vite:format", "options": { "write": true } } }}Nx 的优势在于受影响项目检测——只格式化当前提交影响到的子包:nx format:check --projects=tag:scope:uinx format:write --projects=tag:scope:ui这在大型 monorepo 中比 prettier --write . 高效很多。Lerna 集成Lerna 的 --scope 选项可以针对特定子包执行格式化:lerna exec --scope @my-org/ui -- prettier --write "src/**/*.js"lerna exec --scope @my-org/core -- prettier --check "src/**/*.{ts,tsx}"Lerna 7 之后去除了内置的 lerna run 对 Prettier 的特殊处理,推荐直接在子包的 package.json 里加 format 脚本,然后用 lerna run format 批量执行。性能优化增量格式化——只处理 Git 暂存区中的变更文件:git diff --name-only --diff-filter=ACM HEAD | grep -E '\.(js|ts|tsx)$' | xargs prettier --write并行处理——多核同时跑,适合项目文件数过万的场景:find . -name "*.ts" -not -path "*/node_modules/*" | parallel -j 4 prettier --write缓存机制——Prettier 3.0 原生支持缓存:prettier --write --cache --cache-strategy content "src/**/*.ts"--cache-strategy content 基于文件内容哈希判断是否需要重新格式化,比默认的 metadata 策略更准确。首次运行生成缓存,后续未修改的文件直接跳过。真实场景:在一个 200+ 子包的 monorepo 中,全量 prettier --check . 需要 45 秒。加上缓存后,二次运行降至 3 秒以内。配合 lint-staged 只处理暂存文件,提交时的格式化检查几乎无感。CI/CD 集成在 GitHub Actions 中配置格式化检查:name: Format Checkon: [push, pull_request]jobs: format: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' - run: npm ci - run: npm run format:check关键点:CI 中必须用 --check(只检查不修改),而不是 --write。如果格式不合格,CI 直接报错,开发者本地 format 后重新提交。如果用 Turborepo,可以配合缓存进一步加速:- uses: actions/cache@v4 with: path: .turbo key: turbo-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}- run: npx turbo format:check常见问题排查问题1:子包格式化规则不生效检查子包目录下是否有自己的 .prettierrc。如果存在,它会完全覆盖根配置。删除子包的 .prettierrc,改用根目录的 overrides 来定制规则。问题2:Prettier 和 ESLint 反复修改同一行确认 eslint-config-prettier 放在了 extends 数组的最后一位。如果放在前面,后续配置会重新开启被关闭的规则。问题3:CI 中格式检查通过但本地不通过(或反过来)通常是 Prettier 版本不一致导致的。在 monorepo 根目录统一安装 Prettier,子包不要单独安装。用 pnpm ls prettier 检查是否有多个版本。问题4:格式化速度过慢按优先级排查:1) 检查 .prettierignore 是否正确排除了 node_modules 和构建产物;2) 启用 --cache;3) 用 lint-staged 只处理变更文件;4) 考虑并行处理。追问为什么推荐共享配置包而不是根目录 .prettierrc?根目录配置对纯内部 monorepo 足够。但如果某些子包会独立发布到 npm,它们脱离 monorepo 上下文后就失去了根配置。共享配置包作为 npm 依赖,无论在不在 monorepo 中都能生效。Prettier 3.0 有哪些影响 monorepo 的变化?最大的变化是原生缓存支持(--cache)和 ESM 配置文件支持(prettier.config.mjs)。缓存对大型 monorepo 的性能提升显著。ESM 配置则允许在配置文件中动态导入其他模块,比如根据环境变量切换规则。
前端阅读 05月28日 07:24

Prettier 与 ESLint 有什么区别?如何协作使用?

Prettier 与 ESLint 有什么区别?如何协作使用?前端项目中,Prettier 和 ESLint 是最常搭配使用的两个工具,但它们的职责完全不同。理解各自的定位,才能正确配置和协作使用。Prettier 和 ESLint 各自负责什么Prettier 是代码格式化工具,只关心代码长什么样:统一缩进、引号、分号、换行等风格解析代码生成 AST 后重新输出,确保格式完全一致配置项很少(约20个),设计理念是"别吵了,就用这个"支持 JS/TS/CSS/HTML/JSON/Markdown 等多种语言ESLint 是代码质量检查工具,关心代码有没有问题:检测未使用变量、潜在错误、不安全的写法执行团队约定的编码规范(如禁用 var、要求 ===)拥有数千条可配置规则和丰富的插件生态仅针对 JavaScript/TypeScript核心区别一句话: Prettier 管"好不好看",ESLint 管"对不对"。为什么不能只用一个ESLint 虽然也有格式化规则(如缩进、引号),但能力有限且配置复杂。Prettier 的格式化效果更一致、覆盖语言更多,且几乎不需要团队争论配置。反过来,Prettier 完全不做代码质量检查,漏掉未使用变量、错误逻辑等问题会埋下隐患。两者结合是当前前端工程的标准做法。协作配置(ESLint Flat Config)从 ESLint v9 开始,官方推荐使用 Flat Config(eslint.config.js)替代旧版 .eslintrc。新配置方式如下:安装依赖:npm install --save-dev eslint prettier eslint-config-prettier配置 eslint.config.js:import js from "@eslint/js";import prettierConfig from "eslint-config-prettier";export default [ js.configs.recommended, prettierConfig, // 必须放在最后,关闭与 Prettier 冲突的规则 { rules: { "no-unused-vars": "warn", "prefer-const": "error", }, },];配置 .prettierrc:{ "semi": true, "singleQuote": true, "tabWidth": 2, "trailingComma": "es5"}关键点: eslint-config-prettier 必须放在配置数组最后,它会关闭所有与 Prettier 冲突的 ESLint 格式化规则,让 Prettier 独占格式化职责。旧版配置方式(.eslintrc)如果项目仍在使用旧版配置,这样设置:// .eslintrc.jsmodule.exports = { extends: [ "eslint:recommended", "prettier", // 放在最后 ],};eslint-plugin-prettier 还需要吗eslint-plugin-prettier 的作用是把 Prettier 的格式化结果作为 ESLint 规则来报告。Prettier 官方现在不再推荐这种方式,原因是:它让 ESLint 承担了格式化职责,导致运行变慢格式化问题被混在 ESLint 报错中,难以区分推荐做法是让两者各自独立运行编辑器集成在 VS Code 中配置自动格式化,保存时同时生效:// .vscode/settings.json{ "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll.eslint": "explicit" }}保存时先由 Prettier 格式化,再由 ESLint 修复代码质量问题,顺序正确无冲突。Git 提交时自动检查配合 Husky 和 lint-staged,在提交代码时自动运行检查:npm install --save-dev husky lint-stagednpx husky init// package.json{ "lint-staged": { "*.{js,ts}": ["eslint --fix", "prettier --write"], "*.{css,html,md,json}": ["prettier --write"] }}# .husky/pre-commitnpx lint-staged这样只有暂存的文件会被检查,既保证代码质量又不影响提交效率。常见冲突与排查| 问题 | 原因 | 解决方式 ||------|------|----------|| ESLint 报缩进/引号错误 | 格式化规则与 Prettier 冲突 | 确认 eslint-config-prettier 在 extends 最后 || Prettier 格式化后 ESLint 仍报错 | 质量规则报错,非格式问题 | 检查具体规则,质量规则应保留 || 保存时格式化不生效 | 编辑器未配置或扩展未安装 | 检查 VS Code 扩展和 settings.json |可以用以下命令快速排查冲突规则:npx eslint-config-prettier path/to/.eslintrc.js执行顺序总结实际运行时的正确顺序:Prettier 先格式化代码(处理风格)ESLint 再检查代码质量(处理逻辑)两者通过 eslint-config-prettier 隔离职责,互不干扰掌握 Prettier 和 ESLint 的职责边界、正确配置方式以及常见冲突排查,是前端工程化基础设施的基本要求。
前端阅读 05月27日 22:07

Prettier 支持哪些配置文件格式?

答案Prettier 支持以下配置文件格式,按查找优先级从高到低排列:| 优先级 | 文件名 | 格式 ||--------|--------|------|| 1 | package.json 中 prettier 字段 | JSON || 2 | .prettierrc | JSON/YAML || 3 | .prettierrc.json | JSON || 4 | .prettierrc.json5 | JSON5 || 5 | .prettierrc.yml / .prettierrc.yaml | YAML || 6 | .prettierrc.toml | TOML || 7 | .prettierrc.js / .prettierrc.mjs | JS(ESM) || 8 | .prettierrc.cjs | JS(CJS) || 9 | prettier.config.js / prettier.config.mjs | JS(ESM) || 10 | prettier.config.cjs | JS(CJS) |Prettier 3.5+ 还支持 .prettierrc.ts / prettier.config.ts(TypeScript 格式),适合 TS 项目直接复用类型。选哪个? 小项目用 .prettierrc.json,简洁无歧义,编辑器能做 JSON Schema 校验;需要注释或动态逻辑时用 .prettierrc.js;TS 项目可考虑 .prettierrc.ts。// .prettierrc.json — 最常用{ "printWidth": 80, "tabWidth": 2, "semi": true, "singleQuote": true, "trailingComma": "es5", "endOfLine": "lf"}// .prettierrc.js — 需要注释时module.exports = { printWidth: 80, // 每行最大字符数 tabWidth: 2, // 缩进空格数 semi: true, // 行尾分号 singleQuote: true, // 单引号 trailingComma: "es5", endOfLine: "lf",};配置解析机制Prettier 从被格式化文件所在目录开始向上搜索配置文件,直到项目根目录,不支持全局配置,确保不同机器行为一致。如果同时存在 .editorconfig,Prettier 会将其作为基础配置,但 .prettierrc 中的选项优先。overrides 按文件类型定制{ "semi": true, "overrides": [ { "files": ["*.md", "*.json"], "options": { "tabWidth": 4 } } ]}.prettierignore类似 .gitignore,排除不需要格式化的文件:node_modulesdist*.min.js追问Q: .prettierrc 和 .prettierrc.json 有什么区别?没有本质区别。.prettierrc 优先级更高,Prettier 会先尝试按 JSON 解析,失败则尝试 YAML。.prettierrc.json 只按 JSON 解析,语义更明确,编辑器也能做 schema 校验。Q: Prettier 配置和 ESLint 冲突怎么办?安装 eslint-config-prettier 关闭 ESLint 中与 Prettier 冲突的规则即可。不要两边重复定义同一规则。Q: 为什么不推荐在 package.json 中配置?package.json 的 prettier 字段容易被忽略,且该文件本身体积大、职责多,配置混在一起不利于维护和代码审查。
前端阅读 05月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:自动排序 importprettier-plugin-tailwindcss:Tailwind 类名排序prettier-plugin-sort-json:JSON 键排序安装后在 .prettierrc 的 plugins 数组中声明即可。Prettier 也会自动加载 node_modules 下匹配 prettier-plugin-* 或 @scope/prettier-plugin-* 的包。如何开发自定义插件一个完整的插件至少导出 languages、parsers、printers:// my-prettier-plugin/index.jsmodule.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 对象,用 concat、hardline、indent 等 API 拼接格式化输出如果只想对已有语言做预处理,只需在 parser 中实现 preprocess 函数,无需写完整 parser/printer调试方式: 运行 prettier --plugin ./my-prettier-plugin --debug-print-doc file.mylang 可查看生成的 Doc 结构。面试追问方向如果只想在格式化前对代码做预处理(如删除注释),怎么实现? — 在对应 parser 中实现 preprocess 函数即可,不需要自定义整个 parser/printer 链路。Prettier 的 Doc 是什么? — Prettier 内部的中间表示,类似虚拟 DOM。print 返回 Doc 而非字符串,Prettier 再根据行宽等配置将 Doc "渲染"为最终输出,这样能自动处理换行和缩进。插件和 Prettier 内置语言支持的区别? — 内置语言是 Prettier 核心代码的一部分,性能和兼容性更优;插件是独立模块,更新节奏自由但需自行维护与 Prettier 版本的兼容。
前端阅读 05月27日 22:04

使用 Prettier 时常见的问题有哪些?如何解决?

Prettier 配置不生效怎么办?修改 .prettierrc 后格式化无变化,是最常见的坑。排查顺序:先用 prettier --find-config-path <file> 确认实际加载的配置文件,可能被上层目录的配置覆盖;再检查 JSON 语法是否合法(多余逗号是最常见的错误);最后重启编辑器,VS Code 会缓存配置。多配置文件共存时,Prettier 按 .prettierrc > .prettierrc.json > .prettierrc.yml > prettier.config.js 的顺序查找,找到一个就停止。用 --config 显式指定可以彻底消除歧义。 追问: .prettierignore 和 .gitignore 的区别是什么? — .prettierignore 只控制 Prettier 忽略哪些文件,不影响 Git;.gitignore 不被 Prettier 自动读取,除非用 --ignore-path .gitignore 显式指定。如何忽略特定文件的格式化?三种方式,适用场景不同:项目级忽略: .prettierignore 文件,语法与 .gitignore 一致,适合忽略 dist/、vendor/ 等目录行内忽略: // prettier-ignore 注释,只忽略紧跟的下一行// prettier-ignoreconst matrix = [ [1, 2, 3], [4, 5, 6],];部分规则覆盖: overrides 字段,为特定文件类型设置不同规则{ "overrides": [ { "files": "*.md", "options": { "proseWrap": "always" } } ]} 追问: // prettier-ignore 能忽略整个文件吗? — 不能,它只作用于紧跟的下一个语法节点。要忽略整个文件,用 .prettierignore。Prettier 和 ESLint 冲突如何解决?这是面试高频题。冲突根源:ESLint 有格式规则(如缩进、引号),Prettier 也有自己的规则,两者同时作用就会打架。标准解法分两步:安装 eslint-config-prettier,它会关闭所有与 Prettier 冲突的 ESLint 规则(可选) 安装 eslint-plugin-prettier,将 Prettier 格式问题作为 ESLint 错误报告// .eslintrc.jsmodule.exports = { extends: [ 'eslint:recommended', 'plugin:prettier/recommended' // 必须放最后,否则会被前面的配置覆盖 ]};plugin:prettier/recommended 已经包含了 eslint-config-prettier,不需要重复引入。extends 的顺序很关键——后面的配置会覆盖前面的,所以 Prettier 相关配置必须放末尾。 追问: eslint-plugin-prettier 和 prettier-eslint 有什么区别? — eslint-plugin-prettier 让 ESLint 调用 Prettier;prettier-eslint 让 Prettier 的输出再过一遍 ESLint fix。前者是主流方案。大项目格式化太慢怎么办?Prettier 3.x 原生支持 --cache,只格式化变更的文件:prettier --write --cache .配合 lint-staged 只处理暂存文件更高效:{ "lint-staged": { "*.{js,ts}": ["prettier --write"] }}升级版本也有明显收益。Prettier 3 基于 ECMAScript 2024 重写了解析器,格式化速度比 2.x 快 2-3 倍。 追问: --cache 的缓存存在哪里? — 默认存在 node_modules/.cache/prettier,可以通过 --cache-location 自定义路径。VS Code 中 Prettier 保存不格式化?检查清单:安装了 Prettier 扩展settings.json 中设置 "editor.formatOnSave": true"editor.defaultFormatter" 设为 "esbenp.prettier-vscode"如果项目有多个 formatter,需要在 "[javascript]" 等语言设置中指定{ "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode", "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }}多编辑器协作时,加 .editorconfig 统一基础缩进和换行符,避免 Tab/Space 之争。团队版本不一致怎么处理?锁定版本是最直接的办法:// package.json{ "devDependencies": { "prettier": "3.3.3" // 不用 ^ 前缀 }}团队用 npm ci 安装依赖,它会严格按 package-lock.json 安装,忽略 node_modules 中已有的版本。CI 环境同理,npm ci 比 npm install 更可靠。升级 Prettier 大版本时,格式化结果可能变化。正确做法:单独开分支升级,确认无异常再合入主干,不要在功能分支中顺手升级。
前端阅读 05月27日 22:03

Prettier 的 .prettierignore 怎么配置?有哪些常用规则和踩坑点?

.prettierignore 文件怎么写?.prettierignore 放在项目根目录,语法和 .gitignore 完全一致。写好它才能放心跑 prettier --write .,否则会格式化不该动的文件。node_modulesdistbuildcoverage*.min.js*.min.csspackage-lock.jsonpnpm-lock.yamlPrettier 默认会忽略哪些文件?不需要手动写,Prettier 自动忽略:版本控制目录:.git、.svn、.hgnode_modules(除非显式加 --with-node-modules)另外,Prettier 自动读取同目录下的 .gitignore,所以 .gitignore 里已经排除的文件不需要在 .prettierignore 里重复写。四种忽略模式怎么用?1. 目录忽略node_modules**/dist2. 扩展名忽略*.min.js*.min.css*.d.ts3. 路径通配符src/**/*.generated.ts!src/vendor/*.js! 是否定模式,表示"前面忽略的里面,这条除外"。4. 行内忽略(prettier-ignore 注释)不想格式化某一段代码,在上方加注释:// prettier-ignoreconst matrix = [ [1, 000, 000], [0, 1, 000], [0, 000, 1]];HTML 里用 <!-- prettier-ignore -->,Markdown 里用 <!-- prettier-ignore -->,CSS 里用 /* prettier-ignore */。每种文件类型都有对应的注释语法。CLI 相关的忽略参数有哪些?--ignore-path .prettierignore.custom:指定自定义 ignore 文件路径--with-node-modules:取消默认对 node_modules 的忽略--list-different(别名 -l):只列出不符合格式的文件名,CI 场景常用# 用自定义 ignore 文件格式化prettier --write --ignore-path .prettierignore.custom "src/**/*.js"# CI 中检查是否有未格式化的文件prettier --check "src/**/*.js"常见踩坑ignore 规则写了不生效? 检查文件是否放在项目根目录,语法是否和 .gitignore 一致。想格式化被忽略的文件? 直接传绝对路径给 prettier,ignore 规则不拦截绝对路径。.prettierignore 和 .gitignore 规则冲突怎么办? .prettierignore 优先级更高。如果 .gitignore 排除了某个文件,但 .prettierignore 没有排除,Prettier 仍会格式化它。