From 58f6088f66cc7e79a325a0a569f166ae1646d49f Mon Sep 17 00:00:00 2001 From: ilia Date: Tue, 24 Mar 2026 23:37:25 -0400 Subject: [PATCH] fix(pwa,deploy): faster SW takeover, verify SITE_ROOT vs nginx - Workbox: skipWaiting, clientsClaim, cleanupOutdatedCaches - NetworkFirst for navigations so HTML shell updates after deploy - deploy-site: cmp index.html vs SITE_ROOT; print nginx root hints; SW tips Made-with: Cursor --- scripts/deploy-site.sh | 24 +++++++++++++++++++++++- vite.config.ts | 15 +++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/scripts/deploy-site.sh b/scripts/deploy-site.sh index 5f2fd95..d54c42b 100755 --- a/scripts/deploy-site.sh +++ b/scripts/deploy-site.sh @@ -10,6 +10,7 @@ set -euo pipefail REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" cd "$REPO_ROOT" +# Nginx must use this path as `root` for this site. If wrong, you will still see an old build. SITE_ROOT="${SITE_ROOT:-/var/www/iliadobkin.com}" echo "==> Node $(node -v) (Vite 7 needs 20.19+ or 22.12+)" @@ -35,7 +36,28 @@ if [[ -d "$SITE_ROOT" ]]; then find "$SITE_ROOT" -mindepth 1 -exec rm -rf {} + cp -a "${REPO_ROOT}/dist/." "$SITE_ROOT/" fi - echo "==> Done. Reload nginx if needed: systemctl reload nginx" + + echo "==> Verify publish (fails if SITE_ROOT is not where nginx reads files)" + if ! cmp -s "${REPO_ROOT}/dist/index.html" "${SITE_ROOT}/index.html"; then + echo "ERROR: dist/index.html and ${SITE_ROOT}/index.html differ or one is missing." + echo " Your nginx root is probably NOT ${SITE_ROOT}. Find it with:" + echo " grep -RIn --include='*.conf' 'root\\s' /etc/nginx/" + exit 1 + fi + echo " OK: index.html on disk matches dist (same deploy)." + + echo "==> Nginx roots (check that one of these is SITE_ROOT=${SITE_ROOT})" + if command -v nginx >/dev/null 2>&1; then + nginx -T 2>/dev/null | grep -E 'server_name|^[[:space:]]*root[[:space:]]' | head -60 || true + else + echo " (nginx binary not in PATH — skip)" + fi + + echo "==> Done. Reload: systemctl reload nginx" + echo " If the browser still shows the old UI:" + echo " • Confirm URL hits THIS server (no second host / CDN)." + echo " • Hard refresh (Ctrl+Shift+R) or Incognito." + echo " • DevTools → Application → Service Workers → Unregister, then reload." else echo "WARN: SITE_ROOT '$SITE_ROOT' is not a directory — not copying dist." echo " Set SITE_ROOT to your nginx root, or copy ${REPO_ROOT}/dist/ manually." diff --git a/vite.config.ts b/vite.config.ts index ad7299e..458aab1 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -33,12 +33,27 @@ export default defineConfig({ VitePWA({ registerType: 'autoUpdate', workbox: { + // Ship new SW immediately so deploys are not stuck behind the old cache. + skipWaiting: true, + clientsClaim: true, + cleanupOutdatedCaches: true, // Omitting navigateFallback can still let some hosts/SW setups treat PDF // navigations like SPA routes; denylist keeps real files out of the fallback. navigateFallback: 'index.html', navigateFallbackDenylist: [/\.pdf$/i], // Large binaries in precache inflate Workbox memory during `vite build` on small VPSs. globIgnores: ['**/*.pdf'], + runtimeCaching: [ + { + urlPattern: ({ request }) => request.mode === 'navigate', + handler: 'NetworkFirst', + options: { + cacheName: 'pages', + networkTimeoutSeconds: 3, + expiration: { maxEntries: 32, maxAgeSeconds: 24 * 60 * 60 }, + }, + }, + ], }, // resume.pdf: serve from /resume.pdf; do not precache (cache quota + build RAM). includeAssets: ['logo.png'],