build(tooling): [ENG-11] add module analysis without changing artifacts

This commit is contained in:
Harvey Zhao committed 2026-09-11 22:22:53 +08:00
1 parent 4a9a26d4fc
commit 5efc7f7699
11 files changed
+12673 -16

No files matched your search

File diff suppressed because it is too large. Load diff
+35
View File
@@ -0,0 +1,35 @@
# 构建模块归因
运行 `yarn build artplayer --analyze`,或 `yarn build all --analyze`。正常构建产物与无此参数时一致;分析只写入 refactor/.cache/build-analysis/run-*,latest.json 指向本次目录,不向 dist 或 npm 包加入报告。
每个包/格式的 JSON 保存最终输出的字节数、gzip9 和 SHA-256,以及模块列表、renderedBytes、renderedCodeUnits、originalCodeUnits、保留/移除导出。renderedBytes 对实际模块 code 计算 UTF-8 字节;Rollup 自带长度是其统计时的 UTF-16 代码单元,单独保留而不冒充字节,后续缩进等也会改变 code,二者差值不能仅归因于字符编码。模块数值来自最终压缩前的 Rollup 渲染,不是可以相加的 gzip 贡献;originalCodeUnits 也不是原始 TS 文件大小。真实传输、网络缓存、解析或构造耗时不能由这些数字推导。
scripts/build-analysis.mjs 负责报告;projects.js 解析只对 build 有效的 --analyze;build.js 在已有 banner/global 转换之后挂载报告。正常模式不创建报告目录。refactor/scripts/build.test.mjs 实际构建 TS/JS/Less/SVG/inline worker,并验证分析开关前后三格式字节完全相同、dist 清单不增加文件、报告哈希等于输出哈希。
## CORE-22 首次归因
固定已发布 5.4.0、重构起点 40fcda6a 的工作区源码、当前核心三者分别记录。起点源码使用当前工具链在独立目录重新构建,只用于同工具链归因,不能冒充已发布 tarball。
| 现代核心来源 | 原始字节 | gzip9 |
| --- | ---: | ---: |
| 已发布 5.4.0 | 134037 | 35486 |
| 起点工作区产物 | 134753 | 35735 |
| 起点源码用当前工具链重建 | 134697 | 35703 |
| 当前核心 | 207875 | 58374 |
同工具链对照仍增加 73178 原始字节、22671 gzip 字节;所以主要原因不是工具链切换。Artplayer.STYLE 单独比较只增加 1927 原始字节、277 gzip 字节,不能解释整体增长;独立字符串压缩仅用于诊断,不能从总 gzip 中直接减掉后视作 JS 精确贡献。
按已提交现代产物重新压缩,CORE-23 键盘/焦点为 +6852 gzip 字节,CORE-14 设置树为 +3772,CORE-16 显示模式为 +3223,合计约占起点至当前 gzip 增量的 61%。这些是各次实际提交的净变化,不是每个模块可以独立相加的压缩大小。早期工具函数 TS 迁移的增量为 45 字节,后续增量主要对应行为补齐、资源/竞态修复,不能概括为 TS 语法导致膨胀。
| Rollup 模块组 | 起点渲染字节 | 当前渲染字节 |
| --- | ---: | ---: |
| setting | 17167 | 51289 |
| control | 20634 | 35134 |
| contextmenu | 5841 | 12546 |
| icons | 23394 | 23560 |
| option-validator 单模块 | 4217 | 4217 |
| vendored screenfull 单模块 | 3581 | 3581 |
目录迁移会改变分组,例如 display 从旧 player 中移出,不能只按新目录的正增量计算功能成本。当前最大源码模块是 setting/render.ts,报告中的模块 code 为 11933 UTF-8 字节;Rollup 记录的渲染长度为 11598 代码单元。后续审查应结合它的失败回滚、更新冲突、挂载回调和焦点契约,不能为减小体积删除已有回归所保护的路径。
没有发现 TS、c8、Playwright 或 Vite 运行时进入核心产物。此轮仅完成归因工具和证据,尚未优化生产行为;ENG-PERF-01/02 保持 open,CORE-22 继续审查可避免的开销和构造耗时。不要把解释了来源等同接受了全部成本。
@@ -0,0 +1,15 @@
# CORE-22 核心阶段完整验收
起点为 ENG-08 提交 4a9a26d4,工作区干净,CORE-21/23、PILOT-01、ENG-08/10 前置均已完成。本任务尚在实施,不能视为核心或 npm 发布验收完成。
首先处理 ENG-PERF-01/02:确认核心体积增长的源码/构建来源,保留旧版与候选真实字节和相同格式;对间歇构造耗时继续同环境配对取证。不得通过提高阈值、删除兼容功能或忽略采样差异让报告通过。
随后复查核心公开差异、运行时与声明消费者、资源和完整安装包浏览器矩阵。旧核心/新插件及新核心/旧插件的生态范围、外部 SDK 和物理设备缺口,必须明确链接对应集成/REL 任务,不能把 chapter 试点结果当作全部插件通过。
若归因发现需要独立实施的模块修正,按 execution-gates.md 拆分任务和下游依赖,逐项验收后独立提交。当前尚无优化收益或兼容总验收结论。
## 首轮体积归因
可复用的正式构建分析从本任务拆为 ENG-11,下游依赖已更新;在该前置交付前本任务暂回 todo,保留初步工作,不重复宣称工具实现。当前三格式产物没有变化。详见 [归因说明](../build-analysis.md) 和 [完整数据](../baselines/bundle-attribution.json)。
同工具链下,起点源码构建现代包 gzip 为 35703 字节,当前为 58374 字节;主要增量仍来自实现而非换编译工具。已提交产物对照中,键盘/焦点、设置树和显示模式三阶段合计约占净 gzip 增量六成。接下来审查这些模块的可避免开销与构造耗时,不删除已有回归保护的兼容、清理和错误恢复路径。
@@ -0,0 +1,13 @@
# ENG-11 正式构建模块分析
CORE-22 在处理 ENG-PERF-01 时,需要把实际产物增长与源码模块、历史提交对应。该工具对其他包同样可用,故从核心总验收中拆为独立工程任务;不将归因工具交付算作核心性能问题已解决。
新增可选 `yarn build <package ... | all> --analyze`。独立报告模块读取 Rollup 的实际模块信息并记录最终产物哈希,仍使用同一正式构建脚本、目标、压缩参数、banner 和兼容导出处理。报告在独立 cache 目录,不改变 dist 清单,不开启 sourcemap,不增加运行时依赖。默认构建方式不变。
验证使用既有真实构建夹具:TS、JS、Less、SVG 和 inline worker 的三个格式在分析开关前后字节一致,报告指纹与实际文件一致。实际核心分析结果也与 ENG-08 已验证产物完全一致。另用起点 40fcda6a 的源码在隔离目录和当前工具链重建作归因,清楚区分旧工作区与 npm 发布来源。完整数据及统计限制见 [维护说明](../build-analysis.md)。
收尾核查 Rollup 实现发现其长度属性是 UTF-16 代码单元,而 code 的后续缩进也会改变长度。报告改为对实际模块 code 使用 Buffer.byteLength 计算 UTF-8 字节,保留两种原生长度为独立字段;重新构建两组对照,未将旧长度冒充字节。完整 CI 476 项通过;这项报告字段修正后,lint 和实际三格式构建用例再次通过。
[冻结归因证据](../baselines/bundle-attribution.json) 保存两组各三格式报告、发布基线尺寸、历史提交尺寸、样式探针和构建工具指纹。当前三个 JS 产物与 ENG-08 一致,未改变播放器运行行为、公开接口或版本。类型/浏览器无需为相同字节重复制造新通过记录,CORE-22 的完整验收仍继续。
ENG-11 done,独立本地提交包含实现、测试、文档和计划调整。为了遵守任务前置规则,CORE-22 在该工具交付前暂回 todo,初步归因记录保留;本提交核实后恢复 doing。性能/体积风险仍 open,没有优化收益或发布放行结论。回退只移除分析开关、报告模块、相关测试和文档,不能回滚前置重构成果。
+6 -3
View File
@@ -2,9 +2,9 @@
> 由 tasks.json 生成。请修改数据后运行 `node refactor/scripts/plan.mjs --write`,不要手改本表。
基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 214 项,范围 22 个包及工作区/示例。
基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 215 项,范围 22 个包及工作区/示例。
状态:todo 155 / doing 0 / blocked 0 / done 59 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
状态:todo 155 / doing 0 / blocked 0 / done 60 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。
@@ -84,6 +84,7 @@
| ENG-08 | workspace<br>增加覆盖率、资源与性能报告 | ENG-03, ENG-05, BASE-06 | 覆盖率基线、资源清理断言、性能报告与阈值 | 关键生命周期分支有门槛,报告不靠无意义断言堆数量;将 BASE-06 的同环境多组配对、计时/压缩审查阈值与资源异常分开接入候选,不把历史现象冻结成正常要求 | M | done |
| ENG-09 | workspace<br>建立全包依赖影响和文档检查 | ENG-07, DOC-04 | 共享核心/构建影响映射、文档及每任务完成提交的 Git 审计接入;契约-支持版本-测试 ID-命令-候选/报告-任务的覆盖索引 | 核心变化触发必需生态检查;原有 DOC-01 至 04 基线例外明确,后续 done 任务不能缺失独立 commit;计划/已执行/缺证据分开,识别缺少验证归属的公开契约 | M | todo |
| ENG-10 | workspace<br>建立历史失败分级和测试可靠性规则 | ENG-03, ENG-04, ENG-05, ENG-07, BASE-07 | 历史失败 ID/环境/旧版复现/负责修复任务、逐模块门槛、受控等待与 trace/retry 规则 | 不靠全局忽略或无理由 skip 隐藏问题,新增回归阻止交付,设备缺口和偶发失败单独可见;以 risks.json 为统一差异索引;关闭必须有 resolutionEvidence/rationale,已复现、源码事实、未验证分开,登记不等于豁免 | M | done |
| ENG-11 | workspace<br>增加不改变产物的模块构建分析 | ENG-03, ENG-08 | 正式构建的可选模块归因报告及源码/产物指纹 | 相同构建开关前后三格式字节一致,报告不进入分发包;区分 Rollup 渲染字节与压缩体积,并保留真实工作区/发布来源 | L | done |
## 2.2 GitHub CI/CD
@@ -126,7 +127,7 @@
| CORE-20 | artplayer<br>收敛核心入口与依赖方向 | CORE-14, CORE-15, CORE-18, CORE-19 | Artplayer 门面、初始化依赖与最终目录 | 所有核心自有源码迁移,公开描述符/静态接口/事件差分通过 | H | done |
| CORE-21 | artplayer<br>生成核心声明并校验包内容 | CORE-20, ENG-07 | 由 TS 生成的既有入口声明与三种发布产物 | 内部类型不泄漏,旧 JS/TS 消费者与 i18n 通过;逐项完成 CORE-07 留下的 BASE-TYPE-04/05/07 声明方案,旧合法消费者与实际返回分别留证;不能以虚假的交叉返回类型或改变运行时来掩盖冲突,未决项阻止核心声明出口;处理 CORE-10 / BASE-TYPE-08 的 setter-only 属性虚构 getter 声明,并复核 PlaybackControls 精确视图与旧 toggle 声明共存策略 | H | done |
| CORE-23 | artplayer<br>检查并补齐键盘、焦点与可访问名称 | CORE-13, CORE-14, CORE-17, ENG-05, BASE-04 | 主要控件/设置/模式退出的键盘与焦点回归、名称和字幕可用性检查及必要兼容修正 | 保持旧快捷键和 DOM/CSS 钩子;真实浏览器验证,不以静态属性检查代替交互;处理 BASE-DOM-01 的主要控件 Tab 不可达,保留既有名称与快捷键 | H | done |
| CORE-22 | artplayer<br>核心阶段完整验收 | CORE-21, CORE-23, PILOT-01, ENG-08, ENG-10 | 核心与旧插件的可自动化完整回归、资源/性能及明确外部验证缺口 | 核心自动化和公开差异处置通过;真实环境缺口链接包集成/REL 门槛,阶段完成不代表可公开发布 | H | todo |
| CORE-22 | artplayer<br>核心阶段完整验收 | CORE-21, CORE-23, PILOT-01, ENG-08, ENG-10, ENG-11 | 核心与旧插件的可自动化完整回归、资源/性能及明确外部验证缺口 | 核心自动化和公开差异处置通过;真实环境缺口链接包集成/REL 门槛,阶段完成不代表可公开发布 | H | todo |
## 5 包迁移:artplayer-plugin-chapter
@@ -435,6 +436,7 @@
- ENG-07: [记录](changes/2026-09-10-ENG-07-package-consumers.md) [记录](baselines/package-validation.json)
- ENG-08: [记录](coverage-performance.md) [记录](baselines/quality-validation.json) [记录](changes/2026-09-11-ENG-08-quality-reports.md)
- ENG-10: [记录](changes/2026-09-10-ENG-10-test-reliability.md) [记录](test-reliability.md)
- ENG-11: [记录](build-analysis.md) [记录](baselines/bundle-attribution.json) [记录](changes/2026-09-11-ENG-11-build-analysis.md)
- PILOT-01: [记录](changes/2026-09-10-PILOT-01-chapter.md) [记录](baselines/pilot-validation.json)
- CORE-01: [记录](changes/2026-09-10-CORE-01-typed-utils.md) [记录](baselines/core-utils-validation.json)
- CORE-02: [记录](changes/2026-09-11-CORE-02-typed-emitter.md) [记录](baselines/emitter-validation.json)
@@ -458,6 +460,7 @@
- CORE-20: [记录](changes/2026-09-11-CORE-20-entry.md) [记录](baselines/entry-validation.json)
- CORE-21: [记录](changes/2026-09-11-CORE-21-public-declarations.md) [记录](baselines/core-declarations-validation.json) [记录](core-public-types.md) [记录](typechecking.md)
- CORE-23: [记录](changes/2026-09-11-CORE-23-keyboard-focus.md) [记录](baselines/keyboard-validation.json)
- CORE-22: [记录](changes/2026-09-11-CORE-22-core-acceptance.md) 初步体积归因已执行;先独立交付新增前置 ENG-11 分析工具,再恢复核心完整验收。
- PKG-CHAPTER-01: [记录](changes/2026-09-10-PKG-CHAPTER-01-contract.md) [记录](baselines/chapter-contract.md)
- PKG-CHAPTER-02: [记录](changes/2026-09-10-PKG-CHAPTER-02-tests.md) [记录](baselines/chapter-validation.json)
- PKG-CHAPTER-03: [记录](changes/2026-09-10-PKG-CHAPTER-03-typescript-modules.md) [记录](baselines/chapter-migration-validation.json)
+8
View File
@@ -1,5 +1,13 @@
# 进度与证据
## 最新完成:ENG-11 构建归因;CORE-22 保留待验收
新增正式构建 --analyze 开关,三个格式的产物字节不变,报告仅写本地缓存。实际构建夹具覆盖 TS/JS/Less/SVG/worker,并验证分析前后内容和清单一致。476 项 CI 通过,最终报告计量修正后另跑 lint 与实际构建测试通过;当前核心三格式均与 ENG-08 指纹一致。
起点源码用当前工具链重建后 gzip 35703 字节,当前 58374;样式单独只增加 277 gzip 字节。历史产物表明键盘/焦点、设置树和显示模式三阶段贡献约六成净增量,没有发现 TS/测试工具进入播放器。模块渲染计量和压缩差异分开记录,见 [归因说明](build-analysis.md)、[证据](baselines/bundle-attribution.json) 和 [交付记录](changes/2026-09-11-ENG-11-build-analysis.md)。这不是优化收益或风险关闭。
工具从核心总验收拆为独立任务,总计 215 项,60 done、155 todo。ENG-11 以独立本地 commit 交付;核实后恢复 CORE-22 doing,继续审查实际开销和核心完整兼容性。ENG-PERF-01/02 保持 open,没有 push/publish/tag/merge。
## 最新完成:ENG-08 覆盖率、资源与性能报告
覆盖率统计核心/chapter 的 224 个运行时文件,明确列出 26 个类型或第三方排除项。首轮发现 file URL 与路径过滤不一致,产生虚假 100% 行覆盖率/零函数分支;已通过原始 V8 数据定位并修复到独立归一化阶段,保留原始文件。真实 esbuild/Vite 映射回归覆盖未执行分支、未导入文件、缺失/过期源码和无效计数。
+15 -1
View File
@@ -7,7 +7,7 @@ import { pathToFileURL } from 'node:url'
import vm from 'node:vm'
import { getEntryFile, parseProjects } from '../../scripts/projects.js'
import { createRebuildQueue } from '../../scripts/rebuild.js'
import { refactorDir } from './releases.mjs'
import { hash, refactorDir } from './releases.mjs'
const root = path.resolve(refactorDir, '..')
test('Package CLI rejects ambiguous requests and never accepts inherited project names', () => {
@@ -15,6 +15,9 @@ test('Package CLI rejects ambiguous requests and never accepts inherited project
assert.deepEqual(parseProjects(['all'], projects, 'build').names, Object.keys(projects))
assert.deepEqual(parseProjects(['artplayer', 'artplayer'], projects, 'build').names, ['artplayer'])
assert.equal(parseProjects(['artplayer', '--no-open'], projects, 'dev').open, false)
assert.equal(parseProjects(['artplayer', '--analyze'], projects, 'build').analyze, true)
assert.equal(parseProjects(['all', '--analyze'], projects, 'build').analyze, true)
assert.throws(() => parseProjects(['artplayer', '--analyze'], projects, 'dev'))
for (const args of [['all', 'artplayer'], ['constructor'], ['../artplayer'], ['--unknown']])
assert.throws(() => parseProjects(args, projects, 'build'))
assert.throws(() => parseProjects(Object.keys(projects), projects, 'dev'))
@@ -99,6 +102,17 @@ test('Normal build CLI compiles TypeScript, JS, Less, SVG and inline worker into
check(exported)
}
check((await import(pathToFileURL(path.join(dist, `${name}.mjs`)))).default)
const original = Object.fromEntries(fs.readdirSync(dist).map(file => [file, hash(fs.readFileSync(path.join(dist, file)))]))
const analyzed = run([name, '--analyze'])
assert.equal(analyzed.status, 0, analyzed.stderr)
assert.deepEqual(Object.fromEntries(fs.readdirSync(dist).map(file => [file, hash(fs.readFileSync(path.join(dist, file)))])), original, 'Analysis must not change published artifact bytes or add files to dist')
const { output } = JSON.parse(fs.readFileSync(path.join(directory, 'refactor/.cache/build-analysis/latest.json'), 'utf8'))
const reports = fs.readdirSync(path.join(directory, output)).map(file => JSON.parse(fs.readFileSync(path.join(directory, output, file), 'utf8')))
assert.equal(reports.length, 3)
for (const report of reports) {
assert.equal(report.artifact.sha256, original[report.file])
assert(report.modules.some(item => item.file.endsWith('/src/index.ts') && item.renderedBytes > 0))
}
}
finally {
const relative = path.relative(parent, directory)
+27 -2
View File
@@ -644,6 +644,27 @@
"deliverable": "历史失败 ID/环境/旧版复现/负责修复任务、逐模块门槛、受控等待与 trace/retry 规则",
"acceptance": "不靠全局忽略或无理由 skip 隐藏问题,新增回归阻止交付,设备缺口和偶发失败单独可见;以 risks.json 为统一差异索引;关闭必须有 resolutionEvidence/rationale,已复现、源码事实、未验证分开,登记不等于豁免"
},
{
"id": "ENG-11",
"phase": "2 工程保障",
"title": "增加不改变产物的模块构建分析",
"scope": [
"workspace"
],
"dependsOn": [
"ENG-03",
"ENG-08"
],
"status": "done",
"risk": "L",
"deliverable": "正式构建的可选模块归因报告及源码/产物指纹",
"acceptance": "相同构建开关前后三格式字节一致,报告不进入分发包;区分 Rollup 渲染字节与压缩体积,并保留真实工作区/发布来源",
"evidence": [
"build-analysis.md",
"baselines/bundle-attribution.json",
"changes/2026-09-11-ENG-11-build-analysis.md"
]
},
{
"id": "CI-01",
"phase": "2.2 GitHub CI/CD",
@@ -1203,13 +1224,17 @@
"CORE-23",
"PILOT-01",
"ENG-08",
"ENG-10"
"ENG-10",
"ENG-11"
],
"status": "todo",
"risk": "H",
"deliverable": "核心与旧插件的可自动化完整回归、资源/性能及明确外部验证缺口",
"acceptance": "核心自动化和公开差异处置通过;真实环境缺口链接包集成/REL 门槛,阶段完成不代表可公开发布",
"evidence": []
"evidence": [
"changes/2026-09-11-CORE-22-core-acceptance.md"
],
"reason": "初步体积归因已执行;先独立交付新增前置 ENG-11 分析工具,再恢复核心完整验收。"
},
{
"id": "PKG-CHAPTER-01",
+44
View File
@@ -0,0 +1,44 @@
import { Buffer } from 'node:buffer'
import { createHash } from 'node:crypto'
import fs from 'node:fs'
import path from 'node:path'
import process from 'node:process'
import { gzipSync } from 'node:zlib'
export function createBuildAnalysis() {
const root = process.cwd()
const parent = path.join(root, 'refactor/.cache/build-analysis')
fs.mkdirSync(parent, { recursive: true })
const directory = fs.mkdtempSync(path.join(parent, 'run-'))
fs.writeFileSync(path.join(parent, 'latest.json'), `${JSON.stringify({ output: path.relative(root, directory).replaceAll('\\', '/') })}\n`)
return { root, directory }
}
export function buildAnalysisPlugin({ root, directory }, name, format) {
return {
name: 'artplayer-build-analysis',
generateBundle(_options, bundle) {
for (const chunk of Object.values(bundle).filter(item => item.type === 'chunk')) {
const modules = Object.entries(chunk.modules).map(([id, info]) => {
const normalized = id.replaceAll('\\', '/')
const dependency = normalized.lastIndexOf('/node_modules/')
const file = id.startsWith('\0')
? `virtual:${id.slice(1)}`
: dependency === -1 ? path.relative(root, id).replaceAll('\\', '/') : normalized.slice(dependency + 1)
return { file, renderedBytes: Buffer.byteLength(info.code || ''), renderedCodeUnits: info.renderedLength, originalCodeUnits: info.originalLength, renderedExports: info.renderedExports, removedExports: info.removedExports }
}).sort((a, b) => b.renderedBytes - a.renderedBytes || a.file.localeCompare(b.file))
const report = {
schemaVersion: 1,
name,
format,
node: process.version,
file: chunk.fileName,
artifact: { bytes: Buffer.byteLength(chunk.code), gzip9: gzipSync(chunk.code, { level: 9 }).length, sha256: createHash('sha256').update(chunk.code).digest('hex') },
note: 'Rendered UTF-8 bytes precede final chunk minification; they are not additive compressed sizes or download measurements. Rollup lengths are separately recorded as UTF-16 code units. Original code units describe Rollup input, not raw TypeScript.',
modules,
}
fs.writeFileSync(path.join(directory, `${name}-${format}.json`), `${JSON.stringify(report, null, 2)}\n`)
}
},
}
}
+13 -7
View File
@@ -3,6 +3,7 @@ import path from 'node:path'
import process from 'node:process'
import cpy from 'cpy'
import { build as viteBuild } from 'vite'
import { buildAnalysisPlugin, createBuildAnalysis } from './build-analysis.mjs'
import { getEntryFile, selectProjects } from './projects.js'
import { getGlobalName, getProjects, getViteBuildConfig } from './utils.js'
@@ -27,7 +28,7 @@ const BUILD_FORMATS = {
esm: { format: 'es', ext: '.mjs', target: 'es2020', minify: false },
}
async function build(name, targetName, clean = false) {
async function build(name, targetName, clean = false, analysis) {
const projectDir = projects[name]
const { version } = JSON.parse(fs.readFileSync(path.join(projectDir, 'package.json'), 'utf-8'))
const distDir = path.join(projectDir, 'dist')
@@ -67,6 +68,8 @@ async function build(name, targetName, clean = false) {
max_line_len: false, // No line length limit
},
}
if (analysis)
config.build.rollupOptions.plugins.push(buildAnalysisPlugin(analysis, name, targetName))
await viteBuild({ root: projectDir, ...config })
@@ -77,16 +80,19 @@ async function build(name, targetName, clean = false) {
console.log(`✨ Built@${targetName} ${name}@${version} Time@${Date.now() - startTime}ms Size@${size}kb`)
}
async function buildProject(name) {
await build(name, 'main', true)
await build(name, 'legacy')
await build(name, 'esm')
async function buildProject(name, analysis) {
await build(name, 'main', true, analysis)
await build(name, 'legacy', false, analysis)
await build(name, 'esm', false, analysis)
}
async function runBuild() {
const { names } = await selectProjects(projects, 'build')
const { names, analyze } = await selectProjects(projects, 'build')
const analysis = analyze ? createBuildAnalysis() : undefined
for (const name of names)
await buildProject(name)
await buildProject(name, analysis)
if (analysis)
console.log(`Build analysis: ${analysis.directory}`)
if (names.length)
console.log(`✅ Finished building ${names.length} package(s)!`)
}
+6 -3
View File
@@ -20,9 +20,12 @@ export function getEntryFile(projectDir) {
export function parseProjects(args, projects, command) {
const names = []
let open = true
let analyze = false
for (const arg of args) {
if (arg === '--no-open' && command === 'dev')
open = false
else if (arg === '--analyze' && command === 'build')
analyze = true
else if (arg === '--help')
return { help: true, names: [], open }
else if (arg !== '--')
@@ -31,7 +34,7 @@ export function parseProjects(args, projects, command) {
if (names.includes('all')) {
if (command !== 'build' || names.length !== 1)
throw new Error('Use build all on its own; dev accepts one package')
return { names: Object.keys(projects), open }
return { names: Object.keys(projects), open, analyze }
}
for (const name of names) {
if (!Object.hasOwn(projects, name))
@@ -39,13 +42,13 @@ export function parseProjects(args, projects, command) {
}
if (command === 'dev' && names.length > 1)
throw new Error('dev accepts one package')
return { names: [...new Set(names)], open }
return { names: [...new Set(names)], open, analyze }
}
export async function selectProjects(projects, command) {
const selection = parseProjects(process.argv.slice(2), projects, command)
if (selection.help) {
console.log(command === 'build' ? 'Usage: yarn build [all | package ...]' : 'Usage: yarn dev [package] [--no-open]')
console.log(command === 'build' ? 'Usage: yarn build [all | package ...] [--analyze]' : 'Usage: yarn dev [package] [--no-open]')
return selection
}
if (!selection.names.length) {