MikeyB
MikeyB

Reputation: 490

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!

Upvotes: 12

Views: 9171

Answers (1)

Daniel
Daniel

Reputation: 1205

  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>
    

Upvotes: 4

Related Questions