Nuxt API

useSkewProtection()

Last updated by
Harlan Wilton
in doc: clean up.

The main composable for interacting with Nuxt Skew Protection.

Usage

const skew = useSkewProtection()

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"

isOutdated

  • Type: ComputedRef<boolean>

Whether the user's version is outdated.

const { isOutdated } = useSkewProtection()

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

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 a new version is detected, regardless of whether it affects the current session. Uses Nuxt's built-in app:manifest:update hook.

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.

Consider the case of a user on a blog post when you deploy a new version that only changes the homepage. The user's session is unaffected and they can continue browsing without interruption. In this case, onCurrentChunksOutdated will not trigger.

Under the hood this tracks modules using a service worker.

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
  expires: string
  assets: string[]
  deletedChunks?: 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>
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, isOutdated } = useSkewProtection()

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

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