Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get Socket.io working with Svelte?

I'm trying to get socket.io working with Svelte that I've recently started experimenting with, which is in its stock form as installed by the instructions given at https://svelte.dev/.

I'm at a loss as to why I'm getting bundle.js:4497 GET http://localhost:5000/socket.io/?EIO=3&transport=polling&t=N72840H 404 (Not Found) errors no matter what combinations I try of what I had working on an earlier 'basic' Node.js server, whose relevant code looked like so:

const express = require('express');
const app = express();
const server = http.createServer(app)
const io = require('socket.io')(server,{
    transports: ['websockets', 'polling'],
    upgrade:false,
    cookie:false
});
const sockets = require('./models/socket')(io)

I've tried numerous combinations of the above suggested in various places with alternatives like:

require('http').Server(app)

...why .Server() and not .createServer()? Nobody ever explains. I've tried with app and express and server or app.listen and without, some tutorials/posts have them, others do not - no idea if any of it is a prerequisite or not. Many examples have localhost, many do not. Sometimes with a number after the colon, sometimes not.

On the front end (in the .svelte file) have tried with import io from 'socket.io-client', with a cdn in the index.html file and with <script src="../socket.io/socket.io.js"></script> (no dots, 1 dot, no slash, etc) in the head. The last one was different because it wasn't found before attempting to connect with io(), which is where the persistent error generates.

The io() sometimes is suggested as io.connect(), or io.connect('localhost'), or io.connect('localhost:3000 or 8080 or some other). God knows why.

Is it to do with the way Rollup.js bundling stuff works? I've looked around but nothing is giving any useful leads.

If my post is lacking detail or information, please say so in the comments and I will edit it to provide as much detail as is needed. Thank you!

like image 906
MikeyB Avatar asked Apr 28 '20 19:04

MikeyB


People also ask

Does Socket.IO need a server?

Socket.io, and WebSockets in general, require an http server for the initial upgrade handshake. So even if you don't supply Socket.io with an http server it will create one for you.

How does Socket.IO connection work?

Socket.IO allows bi-directional communication between client and server. Bi-directional communications are enabled when a client has Socket.IO in the browser, and a server has also integrated the Socket.IO package. While data can be sent in a number of forms, JSON is the simplest.


1 Answers

  1. create global store export const socket = writable();
  2. add utility function
import { socket } from "../../store";
import {API_URL} from "../../config"

export const getSocket = async () => {
  const script = document.createElement("script");
  script.src = "/socket-3-0-0.js";
  document.head.appendChild(script);
  
  script.onload = () => {
    const client = io(API_URL)
    socket.set(client)
  }
}
  1. invoke getSocket in _layout
<script>
    onMount(async () => {
        getSocket();
    }
</script>
  1. import store and use
<script>
    import { socket } from "../store";
    $socket?.on("blah", function() {});
</script>

Update:

  1. You can do smth like this in _layout.svelte:

    <script lang="ts">
      function getIoClient(tokens) {
        if (typeof io !== 'undefined') {
          return io(API_URL, {
            transports: ["websocket", "polling", "flashsocket"],
            withCredentials: true,
            query: {
              ...tokens,
            },
          })
        }
      }
    
      async function initSocket() {
        if ($loggedIn) {
          const auth = await getAuth()
    
          socket.set(
            getIoClient({
              id_token: auth?.id_token,
              refresh_token: auth?.refresh_token,
              access_token: auth?.access_token,
              expiry_date: auth?.expiry_date,
            })
          )
        }
      }
    
      async function socketLoaded() {
        await initSocket()
      }
    </script>
    
    <svelte:head>
      {#if $loggedIn}
        <script src="/socket-3-1-3.js" on:load={socketLoaded}></script>
      {/if}
    </svelte:head>
    
like image 72
Danil T Avatar answered Sep 28 '22 10:09

Danil T