Index of every page on this site: llms.txt

useSkewProtection()

Use useSkewProtection() to read version state, manage connections, and handle updates.

Usage

const skew = useSkewProtection()

Options

The lazy option (boolean, default false) controls whether the composable establishes the connection automatically when called in a mounted component. When true, you must call connect() manually.

// Auto-connect on mount (default)
const skew = useSkewProtection()

// Manual connection control
const skew = useSkewProtection({ lazy: true })
skew.connect() // Connect when ready

Returns

manifest

  • Type: Ref<NuxtAppManifestMeta | null>

The current build manifest from builds/latest.json.

const { manifest } = useSkewProtection()

console.log(manifest.value?.id) // Current buildId
console.log(manifest.value?.timestamp) // Build timestamp

clientVersion

  • Type: string

The user's current version (from cookie or buildId).

const { clientVersion } = useSkewProtection()

console.log(clientVersion) // "abc123"

isAppOutdated

  • Type: ComputedRef<boolean>

Whether the user's version is outdated.

const { isAppOutdated } = useSkewProtection()

if (isAppOutdated.value) {
  console.log('User is on an old version')
}

isConnected

  • Type: ComputedRef<boolean>

Whether this tab subscribes to push updates. With shared ownership, a waiting tab also reports connected. The owner opens the SSE/WebSocket connection. Polling uses no push connection.

const { isConnected } = useSkewProtection()

if (isConnected.value) {
  console.log('Connected to update stream')
}

connect()

  • Type: () => void

Manually establish the connection. Only needed when using lazy: true.

const skew = useSkewProtection({ lazy: true })

// Connect when user clicks a button
function handleConnect() {
  skew.connect()
}

disconnect()

  • Type: () => void

Manually close the connection. Useful for cleanup or pausing updates.

const { disconnect } = useSkewProtection()

// Disconnect when leaving a section
onBeforeRouteLeave(() => {
  disconnect()
})

checkForUpdates()

  • Type: () => Promise<void>

Manually trigger an update check.

const { checkForUpdates } = useSkewProtection()

// Check for updates
await checkForUpdates()

onAppOutdated()

  • Type: (callback: (manifest: NuxtAppManifestMeta | null) => void) => void

Triggers when it detects a new version, regardless of whether it affects the current session. Uses Nuxt's built-in app:manifest:update hook.

If an update was already detected, registration immediately calls your callback with the retained manifest.

Use case: Make next page load a hard navigation (forces HTML reload).

const { onAppOutdated } = useSkewProtection()
onAppOutdated((manifest) => {
  console.log('New version available:', manifest?.id)
  // Show passive "Update available" badge
})

onCurrentChunksOutdated()

  • Type: (callback: (payload: ChunksOutdatedPayload) => void) => void

Triggers only when the user's loaded JavaScript modules have been changed in a new deployment.

For example, a user is reading a blog post when you deploy a homepage change. If their loaded chunks stay unchanged, the callback does not run.

A service worker tracks the loaded modules.

If chunk invalidation was already detected, registration immediately calls your callback with the retained payload.

const { onCurrentChunksOutdated } = useSkewProtection()

onCurrentChunksOutdated((payload) => {
  console.log('Deleted chunks:', payload.deletedChunks)
  console.log('Invalidated modules:', payload.invalidatedModules)
  console.log('Passed releases:', payload.passedReleases)

  // Show notification
  alert('Please reload to get the latest version')
})

Type Definitions

interface NuxtAppManifestMeta {
  id: string
  timestamp: number
  skewProtection?: {
    current: string
    versions: Record<string, VersionInfo>
  }
}

interface VersionInfo {
  timestamp: string
}

interface ChunksOutdatedPayload {
  deletedChunks: string[]
  invalidatedModules: string[]
  passedReleases: string[]
}

Examples

Custom Invalidation Handler

const { onCurrentChunksOutdated } = useSkewProtection()

onCurrentChunksOutdated(({ invalidatedModules, passedReleases }) => {
  // Track in analytics
  analytics.track('chunks_outdated', {
    count: invalidatedModules.length,
    modules: invalidatedModules,
    releases: passedReleases
  })

  // Show custom UI
  showUpdateDialog({
    title: 'Update Required',
    message: `${invalidatedModules.length} modules need updating (${passedReleases.length} releases passed)`
  })
})

Version Information Display

<script setup lang="ts">
const { clientVersion, manifest } = useSkewProtection()

const buildDate = computed(() => {
  if (!manifest.value?.timestamp)
    return null
  return new Date(manifest.value.timestamp).toLocaleString()
})
</script>

<template>
  <div class="version-info">
    <p>Your version: {{ clientVersion }}</p>
    <p>Latest version: {{ manifest?.id }}</p>
    <p>Build date: {{ buildDate }}</p>
  </div>
</template>

Programmatic Update Check

Note: Only relevant if you're using polling.

const { checkForUpdates, isAppOutdated } = useSkewProtection()

async function handleUserAction() {
  // Check for updates before critical action
  await checkForUpdates()

  if (isAppOutdated.value) {
    const shouldReload = confirm('A new version is available. Reload now?')
    if (shouldReload) {
      window.location.reload()
    }
  }
  else {
    // Proceed with action
    await performCriticalAction()
  }
}
Was this page helpful?