Victor Modamio
Victor Modamio

Reputation: 65

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...

Upvotes: 3

Views: 1248

Answers (1)

Rich Harris
Rich Harris

Reputation: 29585

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();
  };
});

Upvotes: 4

Related Questions