Real-time Features with WebSockets

WebSockets in Svelte + Laravel

Real-time features enhance user experience by providing immediate feedback and updates without requiring page refreshes. This guide explains how to integrate WebSockets between your Svelte frontend and Laravel backend.

WebSocket Basics

WebSockets provide a persistent connection between client and server, allowing bidirectional communication.

Native WebSocket API

// Basic WebSocket connection in JavaScript
const socket = new WebSocket('ws://example.com/socket');

// Connection opened
socket.addEventListener('open', (event) => {
  console.log('Connected to WebSocket server');
  socket.send(JSON.stringify({ type: 'auth', token: 'user-token' }));
});

// Listen for messages
socket.addEventListener('message', (event) => {
  const data = JSON.parse(event.data);
  console.log('Message from server:', data);
});

// Connection closed
socket.addEventListener('close', (event) => {
  console.log('Disconnected from WebSocket server');
});

// Handle errors
socket.addEventListener('error', (event) => {
  console.error('WebSocket error:', event);
});

Laravel WebSocket Options

Popular Laravel WebSocket Solutions

  • Laravel Echo + Laravel WebSockets - Open-source WebSocket server for Laravel
  • Laravel Echo + Pusher - Pusher is a hosted WebSocket service with a generous free tier
  • Laravel + Socket.IO - Using Socket.IO with Laravel for real-time features

Laravel WebSockets Setup

# Install Laravel WebSockets package
composer require beyondcode/laravel-websockets

# Publish the configuration and migrations
php artisan vendor:publish --provider="BeyondCodeLaravelWebSocketsWebSocketsServiceProvider" --tag="migrations"
php artisan vendor:publish --provider="BeyondCodeLaravelWebSocketsWebSocketsServiceProvider" --tag="config"

# Run migrations to create the websockets tables
php artisan migrate

# Install Laravel Echo and dependencies
npm install laravel-echo pusher-js

Laravel Broadcasting

Laravel's event broadcasting system integrates with WebSockets to send server-side events to the client.

Configure Broadcasting in Laravel

// config/broadcasting.php
'connections' => [
    'pusher' => [
        'driver' => 'pusher',
        'key' => env('PUSHER_APP_KEY'),
        'secret' => env('PUSHER_APP_SECRET'),
        'app_id' => env('PUSHER_APP_ID'),
        'options' => [
            'cluster' => env('PUSHER_APP_CLUSTER'),
            'host' => env('PUSHER_HOST', '127.0.0.1'),
            'port' => env('PUSHER_PORT', 6001),
            'scheme' => env('PUSHER_SCHEME', 'http'),
            'useTLS' => env('PUSHER_SCHEME', 'https') === 'https',
        ],
    ],
],

Create a Broadcast Event

// Create an event
php artisan make:event NewMessage

// app/Events/NewMessage.php
namespace AppEvents;

use IlluminateBroadcastingChannel;
use IlluminateBroadcastingInteractsWithSockets;
use IlluminateBroadcastingPresenceChannel;
use IlluminateBroadcastingPrivateChannel;
use IlluminateContractsBroadcastingShouldBroadcast;
use IlluminateFoundationEventsDispatchable;
use IlluminateQueueSerializesModels;

class NewMessage implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $message;

    public function __construct($message)
    {
        $this->message = $message;
    }

    public function broadcastOn()
    {
        return new Channel('chat');
    }
}

Broadcast the Event

// In a controller or service
use AppEventsNewMessage;

public function sendMessage(Request $request)
{
    $message = [
        'user' => auth()->user()->name,
        'text' => $request->input('message'),
        'time' => now()->toTimeString()
    ];
    
    // Broadcast the event
    broadcast(new NewMessage($message))->toOthers();
    
    return response()->json($message);
}

Svelte + Laravel Echo Integration

Setting Up Laravel Echo in Svelte

// src/lib/echo.js
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';

// Make Pusher available globally
window.Pusher = Pusher;

// Initialize Laravel Echo
const echo = new Echo({
    broadcaster: 'pusher',
    key: import.meta.env.VITE_PUSHER_APP_KEY,
    cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
    wsHost: import.meta.env.VITE_PUSHER_HOST || window.location.hostname,
    wsPort: import.meta.env.VITE_PUSHER_PORT || 6001,
    forceTLS: (import.meta.env.VITE_PUSHER_SCHEME || 'https') === 'https',
    disableStats: true,
    enabledTransports: ['ws', 'wss'],
});

export default echo;

Using Echo in a Svelte Component

<script>
  import { onMount, onDestroy } from 'svelte';
  import echo from '$lib/echo';
  
  let messages = [];
  let channel;
  
  onMount(() => {
    // Subscribe to the channel
    channel = echo.channel('chat');
    
    // Listen for the NewMessage event
    channel.listen('NewMessage', (event) => {
      messages = [...messages, event.message];
    });
  });
  
  onDestroy(() => {
    // Clean up the subscription
    if (channel) {
      channel.unsubscribe();
    }
  });
  
  // Send a message
  async function sendMessage(text) {
    try {
      await fetch('/api/messages', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json',
        },
        body: JSON.stringify({ message: text })
      });
    } catch (error) {
      console.error('Error sending message:', error);
    }
  }
</script>

Private and Presence Channels

Authentication for Private Channels

Private channels require authentication to ensure only authorized users can subscribe.

// Laravel routes/channels.php
Broadcast::channel('private-chat.{id}', function ($user, $id) {
    return $user->id === (int) $id || $user->hasAccessToChat($id);
});

// Svelte component
<script>
  import echo from '$lib/echo';
  
  onMount(() => {
    // Subscribe to a private channel
    const privateChannel = echo.private(`chat.${userId}`);
    
    privateChannel.listen('NewMessage', (event) => {
      messages = [...messages, event.message];
    });
  });
</script>

Presence Channels for User Awareness

Presence channels track who is subscribed, making them perfect for user presence features.

// Laravel routes/channels.php
Broadcast::channel('presence-chat.{roomId}', function ($user, $roomId) {
    if ($user->canJoinRoom($roomId)) {
        return ['id' => $user->id, 'name' => $user->name];
    }
});

// Svelte component
<script>
  import echo from '$lib/echo';
  
  let users = [];
  
  onMount(() => {
    // Subscribe to a presence channel
    const presenceChannel = echo.join(`presence-chat.${roomId}`);
    
    // When someone joins
    presenceChannel.here((members) => {
      users = members;
    });
    
    // When someone joins after we've joined
    presenceChannel.joining((user) => {
      users = [...users, user];
    });
    
    // When someone leaves
    presenceChannel.leaving((user) => {
      users = users.filter(u => u.id !== user.id);
    });
  });
</script>

Interactive WebSocket Demo

This demo simulates a real-time chat application using WebSockets. It's not connecting to a real server but demonstrates the concepts.

Real-time Chat Demo

Status: Disconnected
System 2:06:55 AM
Welcome to the chat!
Alice 2:06:55 AM
Hi everyone!
Bob 2:06:55 AM
Hello Alice!

Real-time Notifications

Notifications (0)

No notifications

Note: This demo simulates notifications being pushed from the server. Connect to see new notifications appear automatically.

Common Real-Time Features

SaaS Real-Time Use Cases

  • Chat and Messaging - Real-time communication between users
  • Notifications - Instant alerts for user actions or system events
  • Live Data Updates - Dashboard with real-time metrics
  • Collaborative Editing - Multiple users editing the same document
  • Status Indicators - Show which users are online or currently active
  • Real-time Validation - Instant feedback during form completion

Best Practices

WebSocket Tips

  • Always Handle Reconnection - Implement robust reconnection logic
  • Optimize Payload Size - Send only the necessary data
  • Authentication - Secure your WebSocket connections
  • Fallback Mechanisms - Have a plan B if WebSockets aren't available
  • Error Handling - Gracefully manage connection issues
  • Testing - Test WebSocket functionality thoroughly

Congratulations!

You've completed all the learning modules for building a SaaS application with Svelte and Laravel! You now have the knowledge to create a modern, responsive, and real-time web application.

Don't forget to check out the official documentation for more advanced topics: