feat(offline): app-shell precache service worker (vite-plugin-pwa) [C1] #197

Merged
developer merged 1 commits from feature/offline-pwa-precache into development 2026-07-06 09:13:57 +00:00
Owner

Part of the PWA offline mode (Phase C). C1 of the C1→C6 stack — precache first, so a cold offline launch actually loads the app (per your ordering choice).

What

Migrate the former install-only public/sw.js to a custom (injectManifest) service worker built from ui/src/sw.ts by vite-plugin-pwa. It precaches the app shell + hashed assets (Workbox — 21 entries, ~684 KiB) so an installed web PWA cold-launches with no network, and falls in-scope navigations back to the precached shell (the hash router resolves the route client-side).

  • Registration stays manual + web-only (injectRegister:false; pwa.svelte.ts skips the mock build + Telegram/VK Mini Apps). The plugin is disabled entirely in the mock build, so Playwright is unperturbed.
  • The Connect stream + API POSTs are never precached nor intercepted (deny-list on the RPC path + /_gm); the landing page + the conditional polyfill bundle are excluded from the precache.
  • Removed public/sw.js; the served path (dist/sw.js at /app/) is unchanged, so the gateway serving + the existing registration are untouched.

Flags for review

  • ⚠️ New dev deps: vite-plugin-pwa + workbox-{core,precaching,routing} — dev-only (not in the app bundle), but workbox-build drags ~320 transitive packages into the lockfile. That's the cost of the Workbox route you chose in round-3. A hand-rolled ~30-line vite plugin (like the existing emitPolyfills) injecting the asset list into a plain SW would add zero deps, at the cost of reimplementing Workbox's precache-revisioning/cleanup. Flagging in case the dep weight changes your mind — I went with your Workbox choice.
  • No main-bundle impact: the SW is a separate file; the gate stays 112.0 / 113.
  • Offline cold-launch is contour-verified — the mock e2e harness disables the SW, so there is no automated offline-launch e2e. Please kick the tyres on the contour: install → go offline → relaunch.

Tests

Go: gateway webui (the /app/sw.js-served-as-JS test) unaffected. UI: check (0 errors), unit (470), e2e (196, Chromium + WebKit), build (generates dist/sw.js, 21 precache entries; the mock build emits no SW), bundle gate 112.0 / 113.

Next: C6 (offline lobby — network gating + reuse NewGame gated to vs_ai+offline for creation + list local games + disable online affordances) stacks on this.

Part of the PWA **offline mode** (Phase C). **C1** of the C1→C6 stack — precache first, so a cold offline launch actually loads the app (per your ordering choice). ## What Migrate the former install-only `public/sw.js` to a custom (**injectManifest**) service worker built from `ui/src/sw.ts` by **vite-plugin-pwa**. It **precaches the app shell + hashed assets** (Workbox — 21 entries, ~684 KiB) so an installed web PWA cold-launches with no network, and falls in-scope navigations back to the precached shell (the hash router resolves the route client-side). - Registration stays **manual + web-only** (`injectRegister:false`; `pwa.svelte.ts` skips the mock build + Telegram/VK Mini Apps). The plugin is **disabled entirely in the mock build**, so Playwright is unperturbed. - The Connect stream + API POSTs are never precached nor intercepted (deny-list on the RPC path + `/_gm`); the landing page + the conditional polyfill bundle are excluded from the precache. - Removed `public/sw.js`; the served path (`dist/sw.js` at `/app/`) is unchanged, so the gateway serving + the existing registration are untouched. ## Flags for review - ⚠️ **New dev deps**: `vite-plugin-pwa` + `workbox-{core,precaching,routing}` — dev-only (not in the app bundle), but `workbox-build` drags **~320 transitive packages** into the lockfile. That's the cost of the Workbox route you chose in round-3. A hand-rolled ~30-line vite plugin (like the existing `emitPolyfills`) injecting the asset list into a plain SW would add **zero deps**, at the cost of reimplementing Workbox's precache-revisioning/cleanup. Flagging in case the dep weight changes your mind — I went with your Workbox choice. - **No main-bundle impact**: the SW is a separate file; the gate stays 112.0 / 113. - **Offline cold-launch is contour-verified** — the mock e2e harness disables the SW, so there is no automated offline-launch e2e. Please kick the tyres on the contour: install → go offline → relaunch. ## Tests Go: gateway `webui` (the `/app/sw.js`-served-as-JS test) unaffected. UI: `check` (0 errors), unit (470), e2e (196, Chromium + WebKit), `build` (generates `dist/sw.js`, 21 precache entries; the mock build emits no SW), bundle gate 112.0 / 113. **Next: C6** (offline lobby — network gating + reuse NewGame gated to vs_ai+offline for creation + list local games + disable online affordances) stacks on this.
developer added 1 commit 2026-07-06 09:07:44 +00:00
feat(offline): app-shell precache service worker (vite-plugin-pwa)
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 10s
CI / integration (pull_request) Successful in 18s
CI / ui (pull_request) Successful in 1m11s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m43s
1a95a5f2cb
Migrate the former install-only public/sw.js to a custom (injectManifest)
service worker built from ui/src/sw.ts by vite-plugin-pwa. It precaches the
app shell + hashed assets (Workbox) so an installed web PWA cold-launches with
no network, and falls in-scope navigations back to the precached shell (the
hash router resolves the route client-side). This is the C1 prerequisite for a
usable offline mode: without it a cold offline launch cannot load the bundle.

- ui/src/sw.ts: skipWaiting + clientsClaim + cleanupOutdatedCaches +
  precacheAndRoute(__WB_MANIFEST) + a NavigationRoute fallback to index.html,
  deny-listing the RPC path and /_gm. The Connect stream and API POSTs are
  never precached nor intercepted.
- vite.config.ts: VitePWA(injectManifest); manifest:false (we ship our own),
  injectRegister:false (registration stays manual + web-only in pwa.svelte.ts),
  disabled in the mock build (Playwright unperturbed); landing + polyfills
  excluded from the precache.
- Removed public/sw.js; the registration path (dist/sw.js at /app/) is unchanged.
- New dev deps: vite-plugin-pwa + workbox-{core,precaching,routing}.

Docs: ARCHITECTURE + gateway/README. Offline cold-launch is contour-verified
(the mock e2e harness disables the SW).
owner approved these changes 2026-07-06 09:13:42 +00:00
developer merged commit 99f0a545be into development 2026-07-06 09:13:57 +00:00
developer deleted branch feature/offline-pwa-precache 2026-07-06 09:13:58 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: developer/scrabble-game#197