12

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!

MikeyB
  • 460
  • 1
  • 6
  • 22
  • socket.io works with svelte (and sapper). I have it working with rollup, polka, socket.io and socket.io-client. What port are you using when you call `server.listen()`? – joshnuss Apr 29 '20 at 21:42
  • I've tried 3000,5000 (the localhost), 3030, 8080... it's just too random and I can't figure out what to align it to. Could you explain what difference it actually makes, because it's one of those things that I and probably many others have implemented on working versions without understand jot about it? – MikeyB Apr 29 '20 at 21:48
  • BTW, I have got things working by building the `bundle.js` then calling a separate `app.js` file that contains the socket.io code. So, it's working, but I don't know if that's normal or ideal. Now I'm tackling sequentially calling these in a `script` in `package.json` to try and get the convenience of `livereload` and `nodemon` working at the same time, to not have to make compromises on the way I was working before... – MikeyB Apr 29 '20 at 21:54
  • Have you managed to import "socket.io-client" while bundling withi Rollup? I cannot even ma this work – Tomasz Plonka Nov 11 '20 at 10:11
  • I keep socket.io outside of the rollup process, not tried again since first finding this workaround – MikeyB Nov 12 '20 at 11:45
  • With latest socket io 3.0 and svelte 3.29 I'm getting a `Cannot access 'XMLHttpRequest' before initialization` error when loading the bundle.js. – MikeyB Nov 16 '20 at 14:19
  • Hope it helps anyone else stumbling across this question https://dev.to/tmns/chatting-with-sapper-svelte-and-socket-io-4c6a – awfullyawful Jan 14 '21 at 11:41

1 Answers1

4
  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>
    
Daniel
  • 839
  • 10
  • 20