Vue Quickstart

npm install pusher-js

Composable + component

<script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue';
import Pusher from 'pusher-js';
 
const messages = ref<Array<{ id: string; text: string }>>([]);
let pusher: Pusher | null = null;
 
onMounted(() => {
  pusher = new Pusher(import.meta.env.VITE_PUSHER_KEY, {
    wsHost: 'ws-sa.mawjly.com',
    wssPort: 443,
    forceTLS: true,
    cluster: 'sa',
    enabledTransports: ['ws', 'wss'],
  });
 
  pusher.subscribe('chat').bind('message', (msg) => {
    messages.value.push(msg);
  });
});
 
onUnmounted(() => pusher?.disconnect());
</script>
 
<template>
  <ul>
    <li v-for="m in messages" :key="m.id">{{ m.text }}</li>
  </ul>
</template>

Reusable composable

// composables/useChannel.ts
import { onUnmounted, ref } from 'vue';
import Pusher from 'pusher-js';
 
let _pusher: Pusher | null = null;
function getPusher() {
  if (_pusher) return _pusher;
  _pusher = new Pusher(import.meta.env.VITE_PUSHER_KEY, {
    wsHost: 'ws-sa.mawjly.com',
    wssPort: 443,
    forceTLS: true,
    cluster: 'sa',
    enabledTransports: ['ws', 'wss'],
  });
  return _pusher;
}
 
export function useChannel<T>(channel: string, event: string) {
  const events = ref<T[]>([]);
  const ch = getPusher().subscribe(channel);
  const handler = (e: T) => events.value.push(e);
  ch.bind(event, handler);
  onUnmounted(() => {
    ch.unbind(event, handler);
    getPusher().unsubscribe(channel);
  });
  return events;
}