Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Websockets in Sapper

I have a readable store in Svelte that looks like this:

const state = {};
export const channels = readable(state, set => {
        let st = state;
        let socket = new WebSocket("ws://127.0.0.1:5999");
    
        socket.onmessage = function (event) {
          var datastr = event.data.split(':');
          st[datastr[0]].value = datastr[1];
          st[datastr[0]].timestamp = Date.now();
                    set(st)
        };
          return () => {
                    socket.close()
                }
    
});

When I import it to my Svelte App works. But if I put that App.svelte as my index.svelte running on Sapper, it doesnt work at first. It says error 500 websocket is not defined. Once I reload the page in the browser start to work... I have try to parse a function that creates the store instead:

export const getChannel = () => {
 // here my store
return {...store}
}

and then creating the store inside a onMount() like this:

onMount( ()=> {
    const channel = getChannel();
});

But doesnt seem to do the trick... What do I miss? Note: If a just replace the store by a simple writable, and create the websocket onMount(), it works without any problem. I just only wanted to put all the communication inside the store as a readable...

like image 887
Victor Modamio Avatar asked Dec 05 '25 14:12

Victor Modamio


1 Answers

In Sapper, code in components (or imported into components) is executed in Node during server-side rendering unless it's put inside onMount (which doesn't run on the server, because there's no 'mounting' happening) or an if (process.browser) {...} block, or something equivalent.

That includes things like references to $channels causing channels.subscribe(...) to be called during initialisation.

Since there's no WebSocket global in Node, creating that subscription will fail. The simplest workaround is probably a simple feature check:

const state = {};
export const channels = readable(state, (set) => {
  if (typeof WebSocket === 'undefined') return;

  let st = state;
  let socket = new WebSocket("ws://127.0.0.1:5999");

  socket.onmessage = function (event) {
    var datastr = event.data.split(":");
    st[datastr[0]].value = datastr[1];
    st[datastr[0]].timestamp = Date.now();
    set(st);
  };
  return () => {
    socket.close();
  };
});
like image 96
Rich Harris Avatar answered Dec 08 '25 05:12

Rich Harris



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!