Prettier 构建脚本完全指南:从 yarn build 到 npm 发布的产物流水线
【免费下载链接】prettierPrettier is an opinionated code formatter.项目地址: https://gitcode.com/gh_mirrors/pr/prettier
Prettier 的发布包并非直接拷贝源码,而是通过scripts/build下的一套构建脚本,用 esbuild 将src目录下的源码与各语言解析器打包成面向 Node.js、浏览器与 Playground 的多格式产物。本文以仓库中的 scripts/build/README.md 为骨架,结合构建器、esbuild 插件与包配置源码,完整讲解构建命令、全部 CLI 标志、包与模块的划分、产物类型,以及体积分析、调试等进阶用法,读完即可独立执行并验证一次完整的 Prettier 构建。
前置要求与入口
根据 scripts/build/README.md,构建脚本要求Node.js 版本>= 16.16。需要注意的是,仓库根目录 package.json 中engines.node为>=22,这是运行整个开发仓库的要求;而构建产物会通过PRODUCTION_MINIMAL_NODE_JS_VERSION(定义于 scripts/utilities/index.js,值为"14")重新写入发布包,保证打包后的dist产物可以在更低的 Node.js 版本上运行。
构建入口定义在根目录 package.json:
"build": "node ./scripts/build/build.js"入口脚本 scripts/build/build.js 的顶层流程如下:
- 调用 scripts/build/parse-arguments.js 解析命令行标志;
- 按
--package过滤出要构建的包(默认构建全部 4 个包); - 若指定
--clean,先删除dist目录; - 依次遍历每个包的模块与文件,调用对应 builder 执行打包,并在终端输出
DONE / FAIL / SKIPPED状态与耗时。
构建的核心是 esbuild:统一的构建器在 scripts/build/builders/javascript-module.js 中实现,它组装了replace-module、evaluate、primitive-define、umd、visualizer等自定义 esbuild 插件(见 scripts/build/esbuild-plugins/ 目录)。
基础用法与--package标志
构建全部包
yarn build不传任何标志时,会构建 scripts/build/packages/index.js 中注册的全部 4 个包:
| 包名 | 配置源文件 | 说明 |
|---|---|---|
prettier | scripts/build/packages/prettier.js | 主包,含核心 API、CLI、文档模块与全部内置语言插件 |
@prettier/plugin-hermes | scripts/build/packages/plugin-hermes.js | Hermes 解析器插件 |
@prettier/plugin-oxc | scripts/build/packages/plugin-oxc.js | Oxc 解析器插件(WASM 版面向浏览器) |
@prettier/plugin-yuku | scripts/build/packages/plugin-yuku.js | Yuku 解析器插件 |
只构建指定包
yarn build --package prettier yarn build --package prettier --package @prettier/plugin-oxc--package可以重复出现,且多个取值必须唯一。在 scripts/build/parse-arguments.js 中,重复的包名会直接抛出'--package' should be unique.;而在 scripts/build/build.js,未知的包名会抛出Unknown package "..."。未指定时默认构建全部 4 个包。
--clean:清理输出目录
yarn build --clean构建前删除dist目录(路径由 scripts/utilities/index.js 中的DIST_DIR定义为仓库根目录下的dist)。实现位于 scripts/build/build.js:若dist存在且是目录则递归删除,若存在但不是目录则报错。源码注释提示目前只清理了顶层dist目录,尚未细化到各包自己的子目录,因此多包开发时建议始终带上--clean,避免旧产物残留。
--playground:仅构建网站所需产物
yarn build --playground该标志让构建只产出 website/ 在线 Playground 需要的文件,其余文件会打印SKIPPED状态跳过。实现上,每个文件在 scripts/build/packages/prettier.js 中被标记playground: true,例如standalone.mjs;scripts/build/build.js 会跳过未标记的文件。插件文件中则只有 ESM 格式产物被标记为 playground 所需(见 scripts/build/packages/prettier.js 的playground: output.format === "esm"),UMD 版本不会为此单独构建。
产物格式与模块划分
Prettier 的发布包按三种格式输出,扩展名定义于 scripts/build/packages/prettier.js:
| 扩展名 | 格式 | 用途 |
|---|---|---|
.mjs | ESM | Node.js 环境与浏览器 ESM 引入 |
.cjs | CommonJS | Node.jsrequire(如src/index.cjs) |
.js | UMD | 浏览器<script>直接引入,挂在全局变量上 |
包内模块(modules)由 scripts/build/packages/prettier.js 组织为:Main(核心 API:index.js/index.cjs/standalone.js)、CLI(bin/prettier、internal/legacy-cli、internal/experimental-cli及 worker)、Doc(文档构建 APIdoc)、各语言插件(plugins/*)以及Meta files(package.json、README.md、LICENSE、THIRD-PARTY-NOTICES.md)。
- 面向 Node.js 的文件由
createNodejsFileConfig生成(scripts/build/packages/config-helpers.js),根据入口是.cjs还是.js自动选择 CJS 或 ESM 输出。 - 面向浏览器/通用环境的文件由
createUniversalFileConfig生成(同文件第 101 行起),同时产出.mjs与 UMD.js两种格式,UMD 全局变量名由umdVariableName指定,例如核心 API 的prettier、文档模块的doc,插件则是prettierPlugins.<pluginName>(见 scripts/build/packages/prettier.js)。
构建指定文件:--file与--save-as
--file
只构建一个或多个特定文件,路径相对于dist目录:
yarn build --file=esm/parser-babel.mjsyarn build --file=standalone.js --file=parser-meriyah.js在 scripts/build/parse-arguments.js 中,每个--file值都会与DIST_DIR拼接成绝对路径存入Set;scripts/build/build.js 逐文件比对,命中才执行构建。--file适合调试单个解析器或 API 入口,避免全量构建。
--save-as
把单个文件的产物保存到其他位置,只能与一个--file搭配使用:
yarn build --file=parser-babel.js --save-as=babel-for-test.js校验逻辑在 scripts/build/parse-arguments.js:文件数必须恰好为 1,且--save-as只能是相对路径(不能越出dist/prettier目录)。该仓库正是用此机制生成vendors/babel-code-frame-for-test.js等测试专用文件(见 scripts/build-babel-code-frame-for-test.js)。
体积分析:--print-size、--compare-size与--report
--print-size:打印产物体积
yarn build --print-size每个文件构建完成后打印其字节数(经过pretty-bytes格式化),实现于 scripts/build/build.js。
--compare-size:与上一发布版本对比
yarn build --compare-size将本次构建产物与node_modules/<包名>/中已安装的上一发布版本逐个对比,打印体积差值(变大显示黄色、变小显示绿色,新文件显示[NEW FILE])。实现位于 scripts/build/build.js。注意两个限制(见 scripts/build/parse-arguments.js):
- 不能与
--no-minify同时使用; - 不能与
--save-as同时使用。
--report:可视化分析包体积
yarn build --report=all yarn build --report=stdout --report=text --report=html--report可重复指定,三种 reporter 格式:
| 值 | 行为 |
|---|---|
html | 生成esbuild-visualizer交互式 HTML 报告,保存为<产物名>.report.html |
text | 生成纯文本报告,保存为<产物名>.report.txt |
stdout | 在控制台直接打印分析报告 |
--report=all等价于同时指定三种格式,但不能与其他--report混用(scripts/build/parse-arguments.js)。报告由 scripts/build/esbuild-plugins/visualizer.js 实现:它开启 esbuild 的metafile,在构建结束时调用esbuild.analyzeMetafile(text/stdout)或esbuild-visualizer(html),将体积分析文件写到产物旁。该功能对排查"哪个依赖把包撑大了"非常有效,例如某次引入新的解析器依赖后,可借此确认体积增长的来源。
调试用:--minify与--no-minify
默认是否压缩由包配置决定(config.mjs/bundler.mjs中控制),这两个标志用于覆盖默认行为,仅供调试,官方建议与--file搭配使用:
yarn build --file=index.js --minify yarn build --file=parser-babel.js --no-minify二者不能同时使用(scripts/build/parse-arguments.js)。--no-minify的产物便于在调试器中阅读打包后的代码,而--minify可用于验证压缩路径下的正确性。
包配置的源码级细节
prettier主包
scripts/build/packages/prettier.js 是整个构建系统的核心配置,它通过replaceModule对第三方依赖做源码级裁剪与替换,这是 Prettier 能把体积控制在合理范围的关键手段,典型手法包括:
- 移除未用功能:将
@babel/parser中未使用的 JSX 实体解码替换为const entity = undefined;,把espree的 token 翻译器直接删掉(options.tokens === true替换为false,见 scripts/build/packages/prettier.js); - 替换实现文件:将
postcss的source-map相关模块替换为空实现类,避免打入source-map依赖(scripts/build/packages/prettier.js); - 注入垫片:为浏览器环境提供
Buffer、structuredClone等全局对象的兜底实现; - 移除调试代码:把
@glimmer/syntax中的DEBUG分支替换为false,把 Angular 编译器里大量与格式化无关的访问器实例删除; - 安全加固:将
@typescript-eslint/typescript-estree中读取process.cwd()、解析项目 tsconfig 的逻辑替换为占位符/空实现,既减小体积也避免打包产物泄露本地路径(scripts/build/packages/prettier.js)。
CLI 部分则把bin/prettier.cjs、传统 CLI(src/cli/index.js)与实验性 CLI(src/experimental-cli/)分别打包,并通过 external 与替换把@prettier/cli、json5、js-yaml、smol-toml等依赖裁剪为最小导出,详见 scripts/build/packages/prettier.js。
插件包
三个内置插件包(@prettier/plugin-hermes、@prettier/plugin-oxc、@prettier/plugin-yuku)各自定义sourceDirectory与distDirectory。其中 scripts/build/packages/plugin-oxc.js 比较特殊:浏览器版index.browser.mjs会先通过buildOxcWasmParser(scripts/build/hacks/build-oxc-wasm-parser.js)编译 Oxc 的 WASM 解析器,再以replaceModule注入产物,且仅该浏览器版被标记为playground: true。
Meta 文件生成
package.json、LICENSE、README.md与THIRD-PARTY-NOTICES.md由 scripts/build/packages/config-helpers.js 统一生成。其中发布版package.json(scripts/build/builders/package-json.js)只保留白名单字段,并把engines.node改写为>=14(PRODUCTION_MINIMAL_NODE_JS_VERSION)、bin指向打包后的 CLI 文件、files字段按实际产物文件列表重写、附带publishConfig。THIRD-PARTY-NOTICES.md由 scripts/build/builders/dependencies-license.js 从依赖许可信息汇总生成,满足发布合规要求。
验证构建产物
构建完成后,所有产物输出到dist/目录,可按包结构验证:
yarn build --clean --package prettier ls dist/prettierdist/prettier下应包含index.mjs、index.cjs、standalone.js、standalone.mjs、doc.js/doc.mjs、plugins/(各语言解析器)、internal/(CLI 相关)以及bin/prettier、package.json、THIRD-PARTY-NOTICES.md等文件。仓库的发布流程 scripts/release/steps/generate-bundles.js 正是先调用本构建系统生成dist,再据此发布到 npm;测试侧则有 scripts/tools/bundle-test/ 对打包产物做冒烟验证。若要单独验证某个插件,可执行:
yarn build --package @prettier/plugin-oxc --print-size --report=stdout该命令只构建 Oxc 插件包、打印体积并输出体积分析报告,是日常开发调试插件产物体积的推荐组合。
小结
Prettier 的构建脚本是一个基于 esbuild 的产物流水线:入口 scripts/build/build.js 负责调度与状态输出,scripts/build/parse-arguments.js 负责全部标志的校验,各包配置(scripts/build/packages/)声明模块、产物格式与依赖裁剪规则。掌握--package、--clean、--playground、--file/--save-as、--print-size/--compare-size/--report、--minify/--no-minify这些标志的组合用法,即可按需完成全量发布构建、仅构建网站产物、单文件调试、依赖体积审计等不同任务。
【免费下载链接】prettierPrettier is an opinionated code formatter.项目地址: https://gitcode.com/gh_mirrors/pr/prettier
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考