mirror of
https://github.com/zoriya/v10.git
synced 2026-08-05 05:37:21 +00:00
chore(ci): fix bundle size measurement and format report (#512)
This commit is contained in:
@@ -62,12 +62,12 @@ jobs:
|
||||
}
|
||||
|
||||
function formatDelta(current, previous) {
|
||||
if (previous === undefined) return '—';
|
||||
if (previous === undefined) return { bytes: '—', pct: '' };
|
||||
const diff = current - previous;
|
||||
if (diff === 0) return '0 B';
|
||||
const sign = diff > 0 ? '+' : '';
|
||||
const pct = ((diff / previous) * 100).toFixed(1);
|
||||
return `${sign}${formatBytes(diff)} (${sign}${pct}%)`;
|
||||
if (diff === 0) return { bytes: '0 B', pct: '0%' };
|
||||
const sign = diff > 0 ? '+' : '-';
|
||||
const pct = Math.abs((diff / previous) * 100).toFixed(1);
|
||||
return { bytes: `${sign}${formatBytes(Math.abs(diff))}`, pct: `${sign}${pct}%` };
|
||||
}
|
||||
|
||||
function statusIcon(current, previous) {
|
||||
@@ -79,36 +79,126 @@ jobs:
|
||||
return pct > 10 ? '🔴' : '🔺';
|
||||
}
|
||||
|
||||
const rows = pr.map(entry => {
|
||||
const prev = baseMap[entry.name];
|
||||
return `| ${entry.name} | ${prev !== undefined ? formatBytes(prev) : '—'} | ${formatBytes(entry.size)} | ${formatDelta(entry.size, prev)} | ${statusIcon(entry.size, prev)} |`;
|
||||
});
|
||||
// Size bar: proportional block characters
|
||||
function sizeBar(bytes, maxBytes) {
|
||||
const width = 8;
|
||||
const filled = Math.max(1, Math.round((bytes / maxBytes) * width));
|
||||
return '█'.repeat(filled) + '░'.repeat(width - filled);
|
||||
}
|
||||
|
||||
const total = pr.reduce((sum, e) => sum + e.size, 0);
|
||||
const baseTotal = base.reduce((sum, e) => sum + e.size, 0);
|
||||
// Group entries by package: @videojs/utils/* -> utils, @videojs/store/* -> store, etc.
|
||||
const groups = new Map();
|
||||
for (const entry of pr) {
|
||||
const match = entry.name.match(/^@videojs\/([^/]+)/);
|
||||
const pkg = match ? match[1] : 'other';
|
||||
if (!groups.has(pkg)) groups.set(pkg, []);
|
||||
groups.get(pkg).push(entry);
|
||||
}
|
||||
|
||||
// First pass: compute per-package totals
|
||||
const pkgData = [];
|
||||
let grandTotalPr = 0;
|
||||
let grandTotalBase = 0;
|
||||
|
||||
for (const [pkg, entries] of groups) {
|
||||
const pkgTotalPr = entries.reduce((s, e) => s + e.size, 0);
|
||||
const pkgTotalBase = entries.reduce((s, e) => s + (baseMap[e.name] ?? 0), 0);
|
||||
const hasBase = entries.some(e => baseMap[e.name] !== undefined);
|
||||
grandTotalPr += pkgTotalPr;
|
||||
grandTotalBase += pkgTotalBase;
|
||||
|
||||
const pkgPrev = entries.length > 1 ? pkgTotalBase : baseMap[entries[0].name];
|
||||
const pkgCur = entries.length > 1 ? pkgTotalPr : entries[0].size;
|
||||
const changed = hasBase && pkgCur !== pkgPrev;
|
||||
|
||||
pkgData.push({ pkg, entries, pkgTotalPr, pkgTotalBase, hasBase, pkgPrev, pkgCur, changed });
|
||||
}
|
||||
|
||||
const maxPkgSize = Math.max(...pkgData.map(p => p.pkgCur));
|
||||
|
||||
// Overview table
|
||||
const overview = [];
|
||||
overview.push('| Package | Size | | Diff | % | |');
|
||||
overview.push('|---|--:|---|--:|--:|:-:|');
|
||||
|
||||
for (const p of pkgData) {
|
||||
const d = formatDelta(p.pkgCur, p.pkgPrev);
|
||||
const icon = p.hasBase ? statusIcon(p.pkgCur, p.pkgPrev) : '';
|
||||
const bar = `\`${sizeBar(p.pkgCur, maxPkgSize)}\``;
|
||||
overview.push(
|
||||
`| **@videojs/${p.pkg}** | **${formatBytes(p.pkgCur)}** | ${bar} | ${p.hasBase ? d.bytes : '—'} | ${p.hasBase ? d.pct : ''} | ${icon} |`
|
||||
);
|
||||
}
|
||||
|
||||
// Detail sections
|
||||
const details = [];
|
||||
details.push('#### Subpath Breakdown');
|
||||
details.push('');
|
||||
|
||||
for (const p of pkgData) {
|
||||
const { pkg, entries, pkgTotalPr, pkgTotalBase, hasBase } = p;
|
||||
|
||||
// Subpath display: @videojs/utils/dom -> ./dom, @videojs/store -> .
|
||||
const displayName = (name) => {
|
||||
const sub = name.replace(`@videojs/${pkg}`, '');
|
||||
return sub ? `.${sub}` : '.';
|
||||
};
|
||||
|
||||
details.push(`<details>`);
|
||||
details.push(`<summary><code>@videojs/${pkg}</code></summary>`);
|
||||
details.push('');
|
||||
details.push('| Subpath | Base | PR | Diff | % | |');
|
||||
details.push('|---|--:|--:|--:|--:|:-:|');
|
||||
|
||||
for (const entry of entries) {
|
||||
const prev = baseMap[entry.name];
|
||||
const d = formatDelta(entry.size, prev);
|
||||
details.push(
|
||||
`| \`${displayName(entry.name)}\` | ${prev !== undefined ? formatBytes(prev) : '—'} | **${formatBytes(entry.size)}** | ${d.bytes} | ${d.pct} | ${statusIcon(entry.size, prev)} |`
|
||||
);
|
||||
}
|
||||
|
||||
if (entries.length > 1) {
|
||||
const d = formatDelta(pkgTotalPr, pkgTotalBase);
|
||||
details.push(
|
||||
`| **total** | **${hasBase ? formatBytes(pkgTotalBase) : '—'}** | **${formatBytes(pkgTotalPr)}** | **${hasBase ? d.bytes : '—'}** | **${hasBase ? d.pct : ''}** | |`
|
||||
);
|
||||
}
|
||||
|
||||
details.push('');
|
||||
details.push('</details>');
|
||||
details.push('');
|
||||
}
|
||||
|
||||
const grandDelta = formatDelta(grandTotalPr, grandTotalBase);
|
||||
|
||||
const marker = '<!-- bundle-size-report -->';
|
||||
const body = [
|
||||
marker,
|
||||
'### 📦 Bundle Size Report',
|
||||
'',
|
||||
'| Package | Base | PR | Delta | |',
|
||||
'|---|---|---|---|---|',
|
||||
...rows,
|
||||
`| **Total** | **${base.length ? formatBytes(baseTotal) : '—'}** | **${formatBytes(total)}** | **${base.length ? formatDelta(total, baseTotal) : '—'}** | |`,
|
||||
...overview,
|
||||
'',
|
||||
`**Total: ${formatBytes(grandTotalPr)}**${grandTotalBase ? ` · ${grandDelta.bytes} · ${grandDelta.pct}` : ''}`,
|
||||
'',
|
||||
'---',
|
||||
'',
|
||||
...details,
|
||||
'---',
|
||||
'',
|
||||
'<details>',
|
||||
'<summary>ℹ️ How to interpret</summary>',
|
||||
'',
|
||||
'Sizes are minified + brotli compressed, measured via [size-limit](https://github.com/ai/size-limit) with esbuild tree-shaking.',
|
||||
'Each package shows its own code size with workspace and peer dependencies externalized.',
|
||||
'Sizes are minified + brotli, measured via [size-limit](https://github.com/ai/size-limit) with esbuild.',
|
||||
'',
|
||||
'| Icon | Meaning |',
|
||||
'|---|---|',
|
||||
'| ✅ | No change |',
|
||||
'| 🔺 | Size increased ≤ 10% |',
|
||||
'| 🔴 | Size increased > 10% |',
|
||||
'| 🔽 | Size decreased |',
|
||||
'| 🆕 | New entry (no baseline) |',
|
||||
'| 🔺 | Increased ≤ 10% |',
|
||||
'| 🔴 | Increased > 10% |',
|
||||
'| 🔽 | Decreased |',
|
||||
'| 🆕 | New (no baseline) |',
|
||||
'',
|
||||
'Run `pnpm size` locally to check current sizes.',
|
||||
'</details>',
|
||||
|
||||
+49
-9
@@ -7,31 +7,71 @@
|
||||
{
|
||||
"name": "@videojs/store/lit",
|
||||
"path": "packages/store/dist/default/lit.js",
|
||||
"import": "*"
|
||||
"import": "*",
|
||||
"ignore": ["@videojs/utils", "@lit/reactive-element", "@lit/context"]
|
||||
},
|
||||
{
|
||||
"name": "@videojs/store/react",
|
||||
"path": "packages/store/dist/default/react.js",
|
||||
"import": "*"
|
||||
"import": "*",
|
||||
"ignore": ["@videojs/utils", "react"]
|
||||
},
|
||||
{
|
||||
"name": "@videojs/core",
|
||||
"path": "packages/core/dist/default/index.js",
|
||||
"import": "*"
|
||||
"import": "*",
|
||||
"ignore": ["@videojs/utils", "@videojs/store"]
|
||||
},
|
||||
{
|
||||
"name": "@videojs/core/dom",
|
||||
"path": "packages/core/dist/default/dom.js",
|
||||
"import": "*"
|
||||
},
|
||||
{
|
||||
"name": "@videojs/react",
|
||||
"path": "packages/react/dist/default/index.js",
|
||||
"import": "*"
|
||||
"import": "*",
|
||||
"ignore": ["@videojs/utils", "@videojs/store"]
|
||||
},
|
||||
{
|
||||
"name": "@videojs/html",
|
||||
"path": "packages/html/dist/default/index.js",
|
||||
"import": "*"
|
||||
},
|
||||
{
|
||||
"name": "@videojs/react",
|
||||
"path": "packages/react/dist/default/index.js",
|
||||
"import": "*",
|
||||
"ignore": ["react"]
|
||||
},
|
||||
{
|
||||
"name": "@videojs/utils/array",
|
||||
"path": "packages/utils/dist/array.js",
|
||||
"import": "*"
|
||||
},
|
||||
{
|
||||
"name": "@videojs/utils/dom",
|
||||
"path": "packages/utils/dist/dom.js",
|
||||
"import": "*"
|
||||
},
|
||||
{
|
||||
"name": "@videojs/utils/events",
|
||||
"path": "packages/utils/dist/events.js",
|
||||
"import": "*"
|
||||
},
|
||||
{
|
||||
"name": "@videojs/utils/function",
|
||||
"path": "packages/utils/dist/function.js",
|
||||
"import": "*"
|
||||
},
|
||||
{
|
||||
"name": "@videojs/utils/object",
|
||||
"path": "packages/utils/dist/object.js",
|
||||
"import": "*"
|
||||
},
|
||||
{
|
||||
"name": "@videojs/utils/predicate",
|
||||
"path": "packages/utils/dist/predicate.js",
|
||||
"import": "*"
|
||||
},
|
||||
{
|
||||
"name": "@videojs/utils/time",
|
||||
"path": "packages/utils/dist/time.js",
|
||||
"import": "*"
|
||||
}
|
||||
]
|
||||
|
||||
+3
-2
@@ -35,18 +35,19 @@
|
||||
"typecheck": "tsc --build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@size-limit/preset-small-lib": "^12.0.0",
|
||||
"@biomejs/biome": "^2.3.11",
|
||||
"@commitlint/cli": "^20.1.0",
|
||||
"@commitlint/config-conventional": "^20.0.0",
|
||||
"@commitlint/format": "^20.0.0",
|
||||
"@size-limit/esbuild": "^12.0.0",
|
||||
"@size-limit/file": "^12.0.0",
|
||||
"@types/node": "^22.18.6",
|
||||
"lint-staged": "^16.2.3",
|
||||
"react": "^18.0.0",
|
||||
"react-compiler-runtime": "^1.0.0",
|
||||
"react-dom": "^18.0.0",
|
||||
"size-limit": "^12.0.0",
|
||||
"simple-git-hooks": "^2.13.1",
|
||||
"size-limit": "^12.0.0",
|
||||
"tsx": "^4.21.0",
|
||||
"turbo": "^2.5.8",
|
||||
"typescript": "^5.9.3"
|
||||
|
||||
+17
-17
@@ -4,13 +4,14 @@
|
||||
"version": "0.1.0-alpha.1",
|
||||
"description": "HTML library for building media players",
|
||||
"license": "Apache-2.0",
|
||||
"keywords": [
|
||||
"media",
|
||||
"player",
|
||||
"html",
|
||||
"ui",
|
||||
"components",
|
||||
"videojs"
|
||||
"main": "dist/default/index.js",
|
||||
"module": "dist/default/index.js",
|
||||
"types": "dist/dev/index.d.ts",
|
||||
"sideEffects": [
|
||||
"./dist/*/define/**/*.js"
|
||||
],
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
@@ -49,15 +50,6 @@
|
||||
"default": "./dist/default/define/media/*.js"
|
||||
}
|
||||
},
|
||||
"sideEffects": [
|
||||
"./dist/*/define/**/*.js"
|
||||
],
|
||||
"main": "dist/default/index.js",
|
||||
"module": "dist/default/index.js",
|
||||
"types": "dist/dev/index.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsdown",
|
||||
"build:watch": "tsdown --watch ./src --no-clean",
|
||||
@@ -81,5 +73,13 @@
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
},
|
||||
"keywords": [
|
||||
"media",
|
||||
"player",
|
||||
"html",
|
||||
"ui",
|
||||
"components",
|
||||
"videojs"
|
||||
]
|
||||
}
|
||||
|
||||
+15
-14
@@ -4,13 +4,12 @@
|
||||
"version": "0.1.0-alpha.1",
|
||||
"description": "React library for building media players",
|
||||
"license": "Apache-2.0",
|
||||
"keywords": [
|
||||
"media",
|
||||
"player",
|
||||
"react",
|
||||
"components",
|
||||
"hooks",
|
||||
"videojs"
|
||||
"main": "dist/default/index.js",
|
||||
"module": "dist/default/index.js",
|
||||
"types": "dist/dev/index.d.ts",
|
||||
"sideEffects": false,
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
@@ -19,12 +18,6 @@
|
||||
"default": "./dist/default/index.js"
|
||||
}
|
||||
},
|
||||
"main": "dist/default/index.js",
|
||||
"module": "dist/default/index.js",
|
||||
"types": "dist/dev/index.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsdown",
|
||||
"build:watch": "tsdown --watch ./src --no-clean",
|
||||
@@ -53,5 +46,13 @@
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
},
|
||||
"keywords": [
|
||||
"media",
|
||||
"player",
|
||||
"react",
|
||||
"components",
|
||||
"hooks",
|
||||
"videojs"
|
||||
]
|
||||
}
|
||||
|
||||
+14
-13
@@ -4,12 +4,12 @@
|
||||
"version": "0.1.0-alpha.1",
|
||||
"description": "Reactive state management for external systems.",
|
||||
"license": "Apache-2.0",
|
||||
"keywords": [
|
||||
"store",
|
||||
"media",
|
||||
"player",
|
||||
"videojs",
|
||||
"reactive"
|
||||
"main": "dist/default/index.js",
|
||||
"module": "dist/default/index.js",
|
||||
"types": "dist/dev/index.d.ts",
|
||||
"sideEffects": false,
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
@@ -28,12 +28,6 @@
|
||||
"default": "./dist/default/react.js"
|
||||
}
|
||||
},
|
||||
"main": "dist/default/index.js",
|
||||
"module": "dist/default/index.js",
|
||||
"types": "dist/dev/index.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsdown",
|
||||
"build:watch": "tsdown --watch ./src --no-clean",
|
||||
@@ -75,5 +69,12 @@
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
},
|
||||
"keywords": [
|
||||
"store",
|
||||
"media",
|
||||
"player",
|
||||
"videojs",
|
||||
"reactive"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,11 +4,7 @@
|
||||
"version": "0.1.0-alpha.1",
|
||||
"description": "Utility functions and helpers for Video.js",
|
||||
"license": "Apache-2.0",
|
||||
"keywords": [
|
||||
"media",
|
||||
"utils",
|
||||
"videojs"
|
||||
],
|
||||
"sideEffects": false,
|
||||
"exports": {
|
||||
"./array": {
|
||||
"types": "./dist/array.d.ts",
|
||||
@@ -61,5 +57,10 @@
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
},
|
||||
"keywords": [
|
||||
"media",
|
||||
"utils",
|
||||
"videojs"
|
||||
]
|
||||
}
|
||||
|
||||
Generated
+6
-14
@@ -20,7 +20,10 @@ importers:
|
||||
'@commitlint/format':
|
||||
specifier: ^20.0.0
|
||||
version: 20.2.0
|
||||
'@size-limit/preset-small-lib':
|
||||
'@size-limit/esbuild':
|
||||
specifier: ^12.0.0
|
||||
version: 12.0.0(size-limit@12.0.0(jiti@2.6.1))
|
||||
'@size-limit/file':
|
||||
specifier: ^12.0.0
|
||||
version: 12.0.0(size-limit@12.0.0(jiti@2.6.1))
|
||||
'@types/node':
|
||||
@@ -2518,11 +2521,6 @@ packages:
|
||||
peerDependencies:
|
||||
size-limit: 12.0.0
|
||||
|
||||
'@size-limit/preset-small-lib@12.0.0':
|
||||
resolution: {integrity: sha512-HHHVQjZmj+8vg7qsHs1dd3Hmn8ygUsE5O2CfxnbCbHOGyUw7VodZGERh/+5ogVrF2DYza/DIo2PnCJZZETdTRA==}
|
||||
peerDependencies:
|
||||
size-limit: 12.0.0
|
||||
|
||||
'@so-ric/colorspace@1.1.6':
|
||||
resolution: {integrity: sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw==}
|
||||
|
||||
@@ -6095,7 +6093,7 @@ packages:
|
||||
tar@7.5.2:
|
||||
resolution: {integrity: sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==}
|
||||
engines: {node: '>=18'}
|
||||
deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me
|
||||
deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
|
||||
|
||||
tar@7.5.7:
|
||||
resolution: {integrity: sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==}
|
||||
@@ -9134,12 +9132,6 @@ snapshots:
|
||||
dependencies:
|
||||
size-limit: 12.0.0(jiti@2.6.1)
|
||||
|
||||
'@size-limit/preset-small-lib@12.0.0(size-limit@12.0.0(jiti@2.6.1))':
|
||||
dependencies:
|
||||
'@size-limit/esbuild': 12.0.0(size-limit@12.0.0(jiti@2.6.1))
|
||||
'@size-limit/file': 12.0.0(size-limit@12.0.0(jiti@2.6.1))
|
||||
size-limit: 12.0.0(jiti@2.6.1)
|
||||
|
||||
'@so-ric/colorspace@1.1.6':
|
||||
dependencies:
|
||||
color: 5.0.3
|
||||
@@ -9709,7 +9701,7 @@ snapshots:
|
||||
sirv: 3.0.2
|
||||
tinyglobby: 0.2.15
|
||||
tinyrainbow: 2.0.0
|
||||
vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)
|
||||
vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)
|
||||
|
||||
'@vitest/utils@3.2.4':
|
||||
dependencies:
|
||||
|
||||
Reference in New Issue
Block a user