'skew-protection:chunks-outdated'

Type: (payload: ChunksOutdatedPayload) => void | Promise<void>

Triggered when the client detects that chunks from their current version have been deleted on the server.

interface ChunksOutdatedPayload {
  deletedChunks: string[]
  invalidatedModules: string[]
  passedReleases: string[]
}
export default defineNuxtConfig({
  hooks: {
    'skew-protection:chunks-outdated': (payload) => {
      console.log('Outdated chunks:', payload.deletedChunks)
      console.log('Releases since client version:', payload.passedReleases)
    },
  },
})

'skew:message'

Type: (message: { type: string, [key: string]: unknown }) => void | Promise<void>

Triggered for every message received from the SSE or WebSocket connection. Useful for building custom functionality on top of the real-time connection.

plugins/skew-listener.client.ts
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.hooks.hook('skew:message', (message) => {
    if (message.type === 'stats') {
      console.log('Active connections:', message.total)
      console.log('Version distribution:', message.versions)
    }

    if (message.type === 'connected') {
      console.log('Connected to server version:', message.version)
    }
  })
})

Message Types

TypeDescriptionPayload
connectedInitial connection acknowledgment{ version, timestamp }
keepalivePeriodic heartbeat{ timestamp }
statsConnection statistics (requires authorization){ total, versions, routes }
stats-unauthorizedSent when stats subscription is denied{}
Stats messages are only sent to connections that pass the skew:authorize-stats hook. See Live Connections for setup.

Connection Config Hooks

These hooks allow you to customize the connection configuration before the connection is established.

'skew:ws:config'

Type: (config: SkewWebSocketConfig) => void | Promise<void>

Customize WebSocket connection settings. The options type extends UseWebSocketOptions from VueUse.

import type { UseWebSocketOptions } from '@vueuse/core'

interface SkewWebSocketConfig {
  url: string
  options: UseWebSocketOptions
}
plugins/skew-config.client.ts
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.hook('skew:ws:config', (config) => {
    // Custom WebSocket URL
    config.url = 'wss://custom-endpoint.example.com/ws'

    // Adjust reconnection behavior
    config.options.autoReconnect = { retries: 5, delay: 10000 }
  })
})
Heartbeat is disabled by default to reduce server load and allow Cloudflare Durable Objects to hibernate. Enable it only if your infrastructure has aggressive idle timeouts (some proxies close connections after 60s of inactivity).
plugins/enable-heartbeat.client.ts
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.hook('skew:ws:config', (config) => {
    // Enable heartbeat for infrastructure with aggressive idle timeouts
    config.options.heartbeat = {
      message: JSON.stringify({ type: 'ping', timestamp: Date.now() }),
      interval: 30000, // ping every 30s
      pongTimeout: 10000 // expect pong within 10s
    }
  })
})

'skew:sse:config'

Type: (config: SkewSSEConfig) => void | Promise<void>

Customize Server-Sent Events connection settings. The options type extends UseEventSourceOptions from VueUse.

import type { UseEventSourceOptions } from '@vueuse/core'

interface SkewSSEConfig {
  url: string
  options: UseEventSourceOptions<string>
}
plugins/skew-config.client.ts
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.hook('skew:sse:config', (config) => {
    // Custom SSE URL
    config.url = '/_custom/sse-endpoint'

    // Adjust reconnection behavior
    config.options.autoReconnect = { retries: 3, delay: 5000 }
  })
})

'skew:adapter:config'

Type: (config: SkewAdapterConfig) => void | Promise<void>

Customize adapter-based connection settings (e.g., Redis, Upstash).

interface SkewAdapterConfig {
  channel: string
  adapterConfig: Record<string, unknown>
}
plugins/skew-config.client.ts
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.hook('skew:adapter:config', (config) => {
    // Override the channel name
    config.channel = 'my-custom-channel'
  })
})
Did this page help you?