Skip to content

Shrink Pages deploy artifact to prevent syncing_files timeouts #211

Description

@kui

Background

The Build and Deploy Pages workflow was failing repeatedly, always in the deploy job's deploy-pages step at syncing_files / deployment_queued (Deployment failed, try again later. / Timeout reached, aborting!). The Continuous Integration (lint/test) workflow was unaffected, and githubstatus.com showed no platform incident during the failure windows. Root cause: the ./public artifact had grown large (~755 MB, ~15k files), and syncing_files scales with the raw unpacked size and file count.

Deleting the largest frozen snapshots already restored a green deploy:

  • Removed public/old/a20 + a21 (~203 MB, ~4.8k files) and their nav links.
  • Removed v1.4/v2.6 source maps (~7.6 MB).

This issue tracks the remaining levers so we can act quickly if the deploy gets flaky again.

How GitHub Pages deploy actually compresses (important)

  • upload-pages-artifact@v4 builds an uncompressed tar, then upload-artifact (zip/deflate, level 6) compresses it. So the uploaded artifact is already deflated — pre-compressing text files does not shrink the upload.
  • The step that fails, syncing_files, operates on the unpacked raw files pushed to the Pages host. It scales with total raw bytes and file count, independent of the zip. So the effective levers are "make the unpacked tree smaller / fewer files".
  • Committing a compressed form (gzip/minify/index) defeats git delta compression (blob bloat), breaks review, and bloats pushes. Prefer compressing in a CI build step (like build:ts already does for JS), keeping the committed source human-readable.

Remaining size-reduction options (measured)

1. Prefab pages: static shell + client-rendered block table (recommended, ~-45 MB)

public/prefabs/*.html is 1866 files / 49.7 MB, of which the block table is 86% (45 MB). That table duplicates data already present in prefab-block-counts.json (9.3 MB) and labels/{lang}/blocks.json.

Keep the 1866 pages at the same URLs (SEO, direct links, no-JS metadata preserved via the 7.1 MB shell), drop only the block table from the HTML, and render it client-side in main.js from the existing prefab-block-counts.json + labels dict. Reusing the existing JSON means no new files, unchanged file count, ~-45 MB, and block labels gain i18n support.

  • Link generators to update: public/prefabs.js:599, src/index/prefab-inspector-handler.ts:156, and the reverse HREF_PATTERN at public/prefabs.js:481.
  • Note: prefab-block-counts.json excludes the air block; decide whether to show/drop it.
  • Lighter-touch fallback (keeps full no-JS): just emit a more compact static block table (drop class="block", drop the duplicated label column) for ~-20 MB.

2. Index-encode prefab-block-counts.json

Block names (12,842 unique, referenced 296,539 times) → dictionary + integer indices: raw 9.3 → 3.3 MB (-65%), gzip 1.46 → 0.85 MB. Requires a loader change. Do the encoding as a CI transform so the committed file stays pretty-printed and stable.

3. Drop source maps from the production build

tools/build.ts prodOpts uses sourcemap: "external", so .js.map files ship in the artifact. Setting sourcemap: false removes ~3-4 MB with no runtime impact.

Not worth it

  • JSON minify: ~-7% only (tab-indented, whitespace is ~12%).
  • JPEG quality reduction: already 280×210 @ q75; ~-2.5–5 MB with visible degradation.
  • HTML can't be pre-gzipped (Pages does not add Content-Encoding); .gz/.jpg are already compressed.

Status

Deploy is currently green after the snapshot deletions, so the above are follow-up optimizations, prioritized by impact: #1 (prefab hybrid) is the single biggest lever.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions