diff --git a/.github/scripts/compare-packages-size.js b/.github/scripts/compare-packages-size.js deleted file mode 100644 index b1e6a5c..0000000 --- a/.github/scripts/compare-packages-size.js +++ /dev/null @@ -1,91 +0,0 @@ -import path from "node:path"; -import { execSync as exec } from "node:child_process"; -import { statSync as stat, existsSync as exists, writeFileSync as write_file } from "node:fs"; -import { globSync as glob } from "glob"; - -const MAIN_WORKTREE = ".worktrees/main"; - -function size(file) { - return exists(file) ? stat(file).size : null; -} - -function format(bytes) { - if (bytes == null) { - return "—"; - } - - return bytes >= 1024 - ? `${(bytes / 1024).toFixed(2)} KB` - : `${bytes} B`; -} - -function delta(pr, main) { - if (pr == null || main == null) { - return null; - } - return pr - main; -} - -function icon(delta) { - if (delta == null) { - return "—"; - } - - if (delta > 0) return "🔴"; - if (delta < 0) return "🟢"; - return ""; -} - -function has_local_origin_main() { - try { - exec('git show-ref --verify --quiet refs/remotes/origin/main', { stdio: ["pipe", "pipe", "pipe"] }); - return true; - } - catch { - return false; - } -} - -function generate_report(files, pr, main) { - let md = ` -### 📦 Bundle size comparison - -| Name | main | PR | Δ | Delta | -|------|-----:|---:|---|-------:| -`; - - for (const file of files) { - const d = delta(pr[file], main[file]); - - md += `| ${path.basename(file)} | ${format(main[file])} | ${format(pr[file])} | ${icon(d)} | ${format(d)} |\n`; - } - - console.log(md); - process.env.SIZE_REPORT_OUTPUT && write_file(process.env.SIZE_REPORT_OUTPUT, md.trim()); -} - -try { - // - // PR build - // - exec("npm run build", { stdio: "inherit" }); - - const pr_files = glob("dist/**/*.min.js"); - const pr_sizes = Object.fromEntries(pr_files.map(f => [f, size(f)])); - - // - // Main build - // - has_local_origin_main() || exec("git fetch origin main", { stdio: "inherit" }); - exec(`git worktree add ${MAIN_WORKTREE} origin/main`, { stdio: "ignore" }); - exec("npm ci --include=dev", { cwd: MAIN_WORKTREE, stdio: "inherit" }); - exec("npm run build", { cwd: MAIN_WORKTREE, stdio: "inherit" }); - - const main_sizes = Object.fromEntries( - pr_files.map(f => [f, size(path.join(MAIN_WORKTREE, f))])); - - generate_report(pr_files, pr_sizes, main_sizes); -} -finally { - exec(`git worktree remove ${MAIN_WORKTREE}`, { stdio: "inherit" }); -} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f504d5a..336f491 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,10 +4,6 @@ on: pull_request: branches: [main] types: [opened, synchronize, reopened, ready_for_review] - paths: - - '**.js' - - '**.ts' - - '**.json' jobs: main: diff --git a/package.json b/package.json index 3528b82..9f901d3 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "scripts": { "build": "cross-env NODE_ENV=production gulp build", "build:debug": "gulp build", - "size-report": "cross-env NODE_ENV=production SKIP_GIT_TAG_RESOLUTION=true node .github/scripts/compare-packages-size.js", + "size-report": "cross-env NODE_ENV=production SKIP_GIT_TAG_RESOLUTION=true node scripts/compare-package-sizes.js", "test": "gulp build && vitest run && playwright test", "test:playwright": "playwright test", "test:vitest": "vitest run" diff --git a/rollup.config.js b/rollup.config.js index 3e28018..68b6be5 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -63,7 +63,7 @@ function create_configuration({ plugin_name, input, format, optimize }) { arguments: true, unsafe_comps: true, unsafe_math: true, - unsafe_methods: true + unsafe_methods: false } })] }, diff --git a/scripts/compare-package-sizes.js b/scripts/compare-package-sizes.js new file mode 100644 index 0000000..758d732 --- /dev/null +++ b/scripts/compare-package-sizes.js @@ -0,0 +1,143 @@ +import path from "node:path"; +import { execSync as exec } from "node:child_process"; +import { globSync as glob } from "glob"; +import { + existsSync as exists, + readFileSync as read_file, + statSync as stat, + writeFileSync as write_file +} from "node:fs"; +import { + brotliCompressSync as brotli, + gzipSync as gzip +} from "node:zlib"; + +const MAIN_WORKTREE = ".worktrees/main"; + +function size(file) { + return exists(file) ? stat(file).size : null; +} + +function gzip_size(file) { + return exists(file) + ? gzip(read_file(file)).length + : null; +} + +function brotli_size(file) { + return exists(file) + ? brotli(read_file(file)).length + : null; +} + +function gather_file_sizes(file) { + return { + no: size(file), + gz: gzip_size(file), + br: brotli_size(file) + }; +} + +function format(length) { + if (length == null) { + return "—"; + } + + return length >= 1024 + ? `${(length / 1024).toFixed(2)} KiB` + : `${length} B`; +} + +function delta(pr, main) { + if (pr == null || main == null) { + return null; + } + return pr - main; +} + +function format_delta(pr, main) { + if (pr == null || main == null) { + return "-"; + } + + let s = format(pr); + let d = pr - main; + + if (d !== 0) { + const sign = d > 0 ? "+" : ""; + s += ` (${sign}${format(d)})`; + } + + return s; +} + +function icon(d) { + if (d == null) { + return "—"; + } + + if (d > 0) return "🔴"; + if (d < 0) return "🟢"; + return ""; +} + +function has_local_origin_main() { + try { + exec('git show-ref --verify --quiet refs/remotes/origin/main', { stdio: "inherit" }); + return true; + } + catch { + return false; + } +} + +function generate_report(files, pr, main) { + let md = ` +### 📦 Bundle size comparison + +| Name | Size | Gzip | Brotli | Δ | +|------|-----:|-----:|-------:|---| +`; + + for (const file of files) { + const d = delta(pr[file].no, main[file].no); + + const no_diff = format_delta(pr[file].no, main[file].no); + const gz_diff = format_delta(pr[file].gz, main[file].gz); + const br_diff = format_delta(pr[file].br, main[file].br); + + md += `| ${path.basename(file)} | ${no_diff} | ${gz_diff} | ${br_diff} | ${icon(d)} |\n`; + } + + console.log(md); + process.env.SIZE_REPORT_OUTPUT && write_file(process.env.SIZE_REPORT_OUTPUT, md.trim()); +} + +try { + // + // PR build + // + exec("npm run build", { stdio: "inherit" }); + + const pr_files = glob("dist/**/*.min.js"); + const pr_sizes = Object.fromEntries(pr_files.map(f => [f, gather_file_sizes(f)])); + + // + // Main build + // + has_local_origin_main() || exec("git fetch origin main", { stdio: "inherit" }); + exec(`git worktree add ${MAIN_WORKTREE} origin/main`, { stdio: "ignore" }); + exec("npm ci --include=dev", { cwd: MAIN_WORKTREE, stdio: "inherit" }); + exec("npm run build", { cwd: MAIN_WORKTREE, stdio: "inherit" }); + + const release_sizes = Object.fromEntries( + pr_files.map(f => [f, gather_file_sizes(path.join(MAIN_WORKTREE, f))])); + + generate_report(pr_files, pr_sizes, release_sizes); +} +catch (e) { + console.log(e); +} +finally { + exec(`git worktree remove -f ${MAIN_WORKTREE}`, { stdio: "inherit" }); +}