refactor: migrate PWA update prompt to nuxt-skew-protection#294
Open
RedStar071 wants to merge 7 commits into
Open
refactor: migrate PWA update prompt to nuxt-skew-protection#294RedStar071 wants to merge 7 commits into
RedStar071 wants to merge 7 commits into
Conversation
…ction The "new deployment available" prompt was previously an implicit side effect of the Workbox service worker (registerType: "prompt" + periodicSyncForUpdates), polling only as often as the SW itself and only for clients that already had it installed. nuxt-skew-protection now owns that job exclusively via its own polling and <SkewNotification>, backed by Netlify Blobs storage (mirroring the existing cache/fetch-cache Nitro mounts). The service worker keeps its original job — offline caching and installability — unchanged, just applying asset updates silently (registerType: "autoUpdate") instead of holding them for a user prompt.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #294 +/- ##
=======================================
Coverage 69.68% 69.68%
=======================================
Files 136 136
Lines 3002 3002
Branches 648 648
=======================================
Hits 2092 2092
Misses 456 456
Partials 454 454
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
Replaces the Vue <Transition> wrapper (and the headless <SkewNotification> slot component) with the same document.startViewTransition pattern used elsewhere in the app (guild/cards.vue, dashboard.vue) — consuming useSkewProtection() directly for script-level control over the transition, guarded by reduced-motion and an already-active-transition check.
Adding nuxt-skew-protection changed pnpm-lock.yaml enough that knip now resolves @nuxtjs/robots as a satisfied dependency on its own, making the suppression entry dead config. knip.ts sets treatConfigHintsAsErrors, so the stale entry was failing CI's "Unused code check" job on PR #294.
dismissed was a sticky boolean that, once set, permanently gated isOpen to false for the rest of the tab's lifetime -- a user dismissing one prompt would never see a reload prompt for any subsequent deployment in that tab. Track the dismissed server version instead, so a newer deploy (a changed serverVersion) re-opens the prompt while the already-dismissed one stays hidden.
Keeps it in sync with the rest of the Nuxt SEO family now that nuxt-skew-protection is installed alongside it. Verified with a full typecheck, lint, knip, unit-test, and production build pass.
In polling mode nuxt-skew-protection registers no connection plugin, so `skew:message` never fires and `serverVersion` stays undefined. Comparing it against the dismissed value made the version-based re-open logic a no-op: the first dismiss stored undefined, and every later polling-detected deployment still saw undefined === undefined, suppressing the prompt for the rest of the tab (and the initial prompt too, since it started undefined). Track the deployment identity via `serverVersion` with a fallback to the manifest build id, which changes on every deployment and is always set when `isAppOutdated` is true. Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
…king serverVersion is only ever populated by nuxt-skew-protection from WS/SSE skew:message events -- never from the polling update strategy this app uses -- so it stayed undefined forever and the previous dismissal tracking never re-opened the prompt for later deployments. Also register onAppOutdated(), which is what actually populates `manifest` (and therefore drives isAppOutdated) on the polling path; without a listener registered, manifest never updates and isAppOutdated could never become true. manifest.id is populated by both the polling and WS/SSE paths, so dismissal tracking now works under either strategy.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🔗 Linked issue
🧭 Context
This change migrates the PWA update prompt logic from the custom
@vite-pwa/nuxtimplementation to thenuxt-skew-protectionmodule, which provides more robust deployment detection and update handling.📚 Description
Changes made:
PWA Prompt Component (
app/components/pwa/Prompt.client.vue)SkewNotificationcomponent, which manages the visibility state and reload/dismiss actions$pwaAPI calls with scoped slot bindings (isOpen,reload,dismiss)PWA Configuration (
config/pwa.ts)periodicSyncForUpdates: 3600— skew-protection handles polling internallyregisterTypefrom"prompt"to"autoUpdate"— the service worker now applies asset updates silently in the background while skew-protection owns deployment detection and the reload promptNuxt Configuration (
nuxt.config.ts)nuxt-skew-protectionto modules listskewProtectionconfig block with:bundleAssets: falseto avoid build-time asset uploads until confirmed safe on NetlifyDependencies (
package.json)nuxt-skew-protection@^1.3.0Why this change:
The
nuxt-skew-protectionmodule provides a more reliable and maintainable approach to detecting new deployments and prompting users to reload. It decouples deployment detection from the service worker lifecycle, uses configurable polling/streaming strategies, and integrates with persistent storage backends for better reliability across deployments.Test Plan
Existing PWA functionality is preserved through the new module. The update prompt UI remains visually and functionally identical; only the underlying state management has changed. CI tests should pass without modification.
https://claude.ai/code/session_019Z94QMdW4SEC1nmLXBM6BL
Need help on this PR? Tag
/codesmithwith what you need. Autofix is enabled.Confidence Score: 5/5
Safe to merge — the migration is self-contained, all changed paths are well-commented, and the version-aware dismiss logic correctly handles the polling case where serverVersion is undefined.
The rewrite of the update prompt is careful and internally consistent. The currentVersion fallback to manifest.value?.id correctly addresses the polling-dismissal problem noted in earlier review rounds. The empty onAppOutdated side-effect, isPrerendered guard, and activeViewTransition check are all justified by comments. No data-loss, auth, or runtime-crash paths were introduced.
No files require special attention.
Reviews (4): Last reviewed commit: "fix(pwa): use manifest id instead of ser..." | Re-trigger Greptile