jimhigson/true-site-size
Measures the real network bytes a browser transfers, from cold cache until your app signals readiness with a performance.mark, and comments the change on pull requests. Captures eager over-loading that file-size diffing cannot see.
View on GitHubTrust Signals
- Scorecard Score
- not yet scored
- Maintenance Recency
- Activelast commit Jul 9, 2026
- License
- MIT
Pinned Snippet
uses: jimhigson/true-site-size@abc874e538b51932c21720a5f86724a9d1f11db0 # no releases — HEAD as of 2026-07-11tags can be moved; commit SHAs can't. why a SHA?
Inputs
| name | description | required | default |
|---|---|---|---|
| journey | JSON array of steps measuring an interactive journey in one browser session: {goto: url}, {click: selector}, {waitFor: selector}, {waitForGone: selector}, {keys: "Enter ArrowDown"}, {script: "..."}, {row: name, mark: markName}. Each row step closes a measurement segment when its performance.mark fires and the network settles; {row: name, marks: [m1, m2]} waits for all the named marks, for apps whose readiness is several independently-loading parts. A row may carry emoji to badge it in the comment (eg {row: menu, mark: menu-ready, emoji: "🎮"}) instead of the auto-assigned colour circle. {startAgain: name} relaunches the browser cold (empty cache) so one journey can measure several apps served from the same build: rows after it accumulate as a new visit with its own cumulative Σ rows and total; as the journey's first step it just names the first visit. Any step may carry afterMark to await an app readiness mark first. Takes precedence over `scenarios`. | — | "" |
| ignore-url-patterns | JSON array of regex strings. Matching requests are excluded from byte counts (still shown in the run-log breakdown, tagged ignored) - for endpoints whose response size legitimately varies, eg live db reads. | — | [] |
| step-timeout-ms | per-step timeout, eg waiting for a click target to appear | — | 20000 |
| settle-timeout-ms | hard cap on waiting for the network to go quiet after a mark - if the app never stops requesting (eg endless polling), the row errors with the in-flight urls named rather than hanging | — | 30000 |
| timeout-ms | hard cap on the entire action (builds and all measurement runs) - a last-resort guard so nothing can hang a ci job indefinitely | — | 900000 |
| scenarios | simple form of `journey`: JSON array like [{"name": "menu", "url": "/", "mark": "menu-ready"}], each entry a navigation then a row. Scenarios run in order in one browser session with a shared http cache, so each reports only its incremental bytes. An entry may carry emoji to badge its row in the comment instead of the auto-assigned colour circle. | — | [] |
| install-command | command to install dependencies in each checkout (empty to skip) | — | "" |
| build-command | command that produces the serveable site | — | npm run build |
| clean-command | command run in the workspace between the head and base builds (empty to skip). The base checks out into a worktree inside the workspace, so without this its build can inherit head's node_modules via upward module resolution; eg "pnpm clean" isolates them. | — | "" |
| serve-dir | directory (relative to the checkout) to serve after building | — | dist |
| compression | simulate the production host's compression - gzip, br, zstd or none. zstd requires the runner's Node to be >= 22.15 (or >= 23.8); gzip, br and none work on any supported Node. | — | gzip |
| compression-level | compression level for the chosen encoding, or "max" for the codec's maximum. Empty uses a moderate default per codec: gzip 8, br 4, zstd 6. Valid ranges: gzip 0-9, br 0-11, zstd 1-22. Ignored when compression is none. | — | "" |
| runs | repeat count. Runs are expected to be byte-identical - the extra run is a determinism self-check, and disagreement is flagged on the comment. | — | 2 |
| settle-ms | ms of network quiet required after the mark before stopping | — | 1500 |
| mark-timeout-ms | ms to wait for each scenario's performance.mark | — | 60000 |
| base-refs | JSON array of refs to compare against (defaults to the PR base branch). Each becomes its own column in the comment, linked to the exact commit and annotated with git describe. eg ["main", "v1.4.0"] compares the PR against both main and a release tag. | — | [] |
| comment | post/update a PR comment with the results | — | true |
| pr-number | PR number to post the comment on. Defaults to the PR that triggered the run; set it to comment from a non-PR event - eg a push to main updating an open release PR's report so it reflects the just-merged code. | — | "" |
| collapse-breakdown | collapse each ref's per-file breakdown into an expandable <details> (true) or show it inline (false). Rows with no changes are always a plain line, since there is nothing to reveal by expanding. | — | true |
| measure-disk | also report the total built size on disk - the compressed (as served, matching `compression`) size of every file in serve-dir, loaded or not, with its own changed-files breakdown. Catches shipped-but-unloaded dead weight. Set false to skip compressing the whole site on large builds. | — | true |
| comment-key | distinguishes multiple uses on one PR - each key maintains its own comment (and is shown in the comment heading) | — | "" |
| spread-tolerance-bytes | byte spread between repeat runs treated as protocol noise rather than non-determinism (h2 header compression varies slightly with request arrival order). Spread above this triggers the determinism warning. | — | 512 |
| minimum-change-threshold | changes smaller than this many bytes display as unchanged - same name, semantics and default as compressed-size-action | — | 1 |
| strip-hash | regex removed from request filenames so the per-file breakdown matches files across base and head despite content hashes (default matches vite/rollup style "-D4zXn_7K." hashes). Empty string disables. | — | (-[a-zA-Z0-9_-]{8})\. |
| github-token | token used to post the PR comment | — | ${{ github.token }} |
Outputs
no outputs