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 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S4wdbGSVzvUDHBWRjSVxfr
58 lines
2.2 KiB
Nginx Configuration File
58 lines
2.2 KiB
Nginx Configuration File
# ⚠️ 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 _;
|
|
|
|
root /usr/share/nginx/html;
|
|
charset utf-8;
|
|
|
|
# Quartz-compatible URLs: /A/B -> A/B.html, /Folder/ -> Folder/index.html
|
|
location / {
|
|
try_files $uri $uri.html $uri/index.html =404;
|
|
}
|
|
|
|
# The notebooks listing builds to notebooks.html *and* has a sibling
|
|
# notebooks/ directory of detail pages. try_files above resolves
|
|
# /notebooks and /notebooks/<slug>, but not the trailing-slash form —
|
|
# a bare directory has no index.html. Map it explicitly so every folder
|
|
# URL on the site keeps working with or without the slash.
|
|
location = /notebooks/ {
|
|
try_files /notebooks.html =404;
|
|
}
|
|
|
|
location /assets/ {
|
|
expires 7d;
|
|
add_header Cache-Control "public";
|
|
}
|
|
|
|
# The ACannons browser build. gzip_static serves the .gz siblings that
|
|
# export-cannons.sh writes, which is the difference between 3.3MB and 9MB
|
|
# on the wire; nginx:alpine ships --with-http_gzip_static_module but has
|
|
# `gzip on` COMMENTED OUT in its base config, so without this the page
|
|
# would go out uncompressed and nothing would say so.
|
|
#
|
|
# no-cache, not `expires`: classes.js and cannons.wasm are stable
|
|
# filenames whose contents change on every rebuild, so a long expiry would
|
|
# serve a stale client against a fresh server until the cache aged out.
|
|
# The browser still caches them and revalidates, which is a 304 and a few
|
|
# bytes on an unchanged build.
|
|
location /cn/ {
|
|
gzip_static on;
|
|
add_header Cache-Control "no-cache";
|
|
}
|
|
|
|
location /_astro/ {
|
|
# content-hashed filenames — safe to cache hard
|
|
expires 365d;
|
|
add_header Cache-Control "public, immutable";
|
|
}
|
|
}
|