From 52bd290ff23fb95f9219e973f642afab4e907893 Mon Sep 17 00:00:00 2001 From: Wesley Ray Date: Fri, 28 Aug 2026 21:34:38 -0400 Subject: [PATCH] Quote the size a visitor actually pays The Play button said "about 3.0 MB". That is the gzipped total, and no public visitor gets it: NPM on the VPS blanks Accept-Encoding for every proxied request at its own nginx.conf:44, so cyrion's gzip_static is never asked and answers raw. The real cost is about 9 MB, and a button whose entire purpose is to be honest about the download was understating it threefold. It now quotes rawBytes. Overstating is the safe direction, and this goes back to wireBytes -- a third of the size -- if NPM is ever made to pass the header through. Falls back to wireBytes for an export made before rawBytes existed. Also puts a warning at the top of nginx.conf. It is bind-mounted as a single FILE, so the inode is pinned and `git pull` gives the file a new one the running container never sees; nothing in auto-build.sh recreates it. The gzip_static rule added an hour ago was not live until the container was force-recreated by hand, and the build was green the whole time. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01S4wdbGSVzvUDHBWRjSVxfr --- deploy/nginx.conf | 9 +++++++++ src/pages/cannons.astro | 19 ++++++++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/deploy/nginx.conf b/deploy/nginx.conf index 4add612..205734b 100644 --- a/deploy/nginx.conf +++ b/deploy/nginx.conf @@ -1,3 +1,12 @@ +# ⚠️ An edit here is NOT live until the container is recreated: +# docker compose -f deploy/docker-compose.yml up -d --force-recreate garden +# This file is bind-mounted as a single FILE, which pins its inode, so the +# `git pull` at the top of every build tick replaces it with a new inode the +# running container never sees. auto-build.sh only builds dist/ -- nothing in +# the automated path touches compose. The build goes green and the config +# simply is not live; `docker exec garden grep ... /etc/nginx/conf.d/default.conf` +# is how you tell. + server { listen 80; server_name _; diff --git a/src/pages/cannons.astro b/src/pages/cannons.astro index 6a59ebf..7641d1c 100644 --- a/src/pages/cannons.astro +++ b/src/pages/cannons.astro @@ -4,7 +4,6 @@ import { loadCannons, cannonsFrameUrl } from '../lib/cannons.mjs'; const build = loadCannons(); const mb = (n) => (n / 1048576).toFixed(1); -const kb = (n) => Math.round(n / 1024); const builtAt = build?.builtAt ? new Date(build.builtAt).toLocaleString('en-US', { year: 'numeric', @@ -13,10 +12,15 @@ const builtAt = build?.builtAt timeZone: 'America/New_York', }) : null; -// What a visitor actually downloads: the export script sums the .gz for -// everything that has one and the file itself for the images, which are -// already-compressed formats gzip would only make bigger. -const overTheWire = build ? mb(build.wireBytes) : null; +// The RAW total, not the gzipped one, because that is what a visitor to +// garden.c0smere.net actually pays: NPM on the VPS blanks Accept-Encoding for +// every proxied request (its own nginx.conf:44), so cyrion's gzip_static is +// never asked and answers uncompressed. The .gz files exist and are correct; +// nothing public reaches them yet. Switch this to build.wireBytes -- about a +// third of the size -- once NPM passes the header through. Overstating the +// cost is the safe direction for a button whose whole job is to be honest +// about it. rawBytes is absent from exports made before this was noticed. +const overTheWire = build ? mb(build.rawBytes ?? build.wireBytes) : null; --- Play - downloads about {overTheWire} MB — {kb(build.bytes['classes.js.gz'])} KB - of client and {mb(build.bytes['cannons.wasm.gz'])} MB of server + downloads about {overTheWire} MB — {mb(build.bytes['classes.js'])} MB + of client, {mb(build.bytes['cannons.wasm'])} MB of server, and the + game's own art