diff --git a/deploy/publish-web.sh b/deploy/publish-web.sh index b3b5509..3da1de2 100755 --- a/deploy/publish-web.sh +++ b/deploy/publish-web.sh @@ -11,7 +11,7 @@ site="/home/jay/srv/sites/upbeatbytes" echo "→ building frontend" ( cd "$repo/frontend" && npm run build ) -echo "→ syncing static site to $site" -rsync -a --delete "$repo/frontend/build/" "$site/" +echo "→ syncing static site to $site (assets first, shell + SW last)" +bash "$repo/deploy/sync-static.sh" "$repo/frontend/build" "$site" echo "✓ Published frontend → https://upbeatbytes.com" diff --git a/deploy/publish.sh b/deploy/publish.sh index cadd5d6..f20c870 100755 --- a/deploy/publish.sh +++ b/deploy/publish.sh @@ -10,8 +10,8 @@ api_compose="/home/jay/srv/upbeatbytes/compose.yaml" echo "→ building frontend" ( cd "$repo/frontend" && npm run build ) -echo "→ syncing static site to $site" -rsync -a --delete "$repo/frontend/build/" "$site/" +echo "→ syncing static site to $site (assets first, shell + SW last)" +bash "$repo/deploy/sync-static.sh" "$repo/frontend/build" "$site" echo "→ rebuilding/refreshing API container" docker compose -f "$api_compose" up -d --build diff --git a/deploy/sync-static.sh b/deploy/sync-static.sh new file mode 100755 index 0000000..d523672 --- /dev/null +++ b/deploy/sync-static.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# Sync the built static site to the live root in an order that avoids deploy-race +# blank screens. rsync isn't atomic, so a naïve `rsync --delete` can briefly serve +# a NEW index.html that points at chunks not synced yet (→ failed load), or delete +# old chunks an in-flight client still needs. Instead: +# 1. new hashed chunks first, and DON'T prune old ones (grace window) +# 2. other static assets (version.json, env.js, icons…), pruning removed files +# 3. the shell HTML — only once its chunks already exist +# 4. the service worker last — a returning client adopts it only after the rest +# Old immutable chunks are pruned after a grace window to bound disk growth. +set -euo pipefail +src="$1"; site="$2" + +rsync -a "$src/_app/immutable/" "$site/_app/immutable/" +rsync -a --delete \ + --exclude='_app/immutable/***' --exclude='index.html' --exclude='service-worker.js' \ + "$src/" "$site/" +rsync -a "$src/index.html" "$site/index.html" +rsync -a "$src/service-worker.js" "$site/service-worker.js" +find "$site/_app/immutable" -type f -mtime +14 -delete 2>/dev/null || true