The main composable for interacting with Nuxt Skew Protection.
Usage
const skew = useSkewProtection()
Options
lazy
- Type:
boolean - Default:
false
When false (default), the connection is established automatically when the composable is 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"
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')
}
isConnected
- Type:
ComputedRef<boolean>
Whether the SSE/WebSocket connection is currently active.
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 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()
}
}