How to use socket.io in Quasar (building an Electron app) ?



  • Hi everybody.
    Quasar Framework is something brand new to me, so I hope I’m able to question this in a manner that makes some sense.

    I’m building a desktop app, migrating from Nuxt to Quasar for two reasons: the in-house support that Quasar offers to build Electron apps, and some unnecessary complications - for my specific case - related to Nuxt (which is great, don’t get me wrong).

    My app is like a chat app for OSC messages, so, its a desktop app with web functionalities.

    In my Nuxt project I had a main.js in the root folder that looks much like this one: https://github.com/nuxt-community/electron-template/blob/master/template/main.js

    I’m aware I won’t need all the Electron part of this file in Quasar, but I’m interested in the server part:

    const http = require('http')
    const server = http.createServer(nuxt.render)
    // listen the server
    server.listen()
    const _NUXT_URL_ = `http://localhost:${server.address().port}`
    console.log(`Nuxt working on ${_NUXT_URL_}`)
    

    because then I would be able to bind socketIO to the server like this:

    const socketIO = require('socket.io')
    const io = socketIO(server)
    

    My double question is how could I get/set something like this within Quasar and where in Quasar’s folder structure the file with it should live?

    bests,
    Gil



  • HI there!
    I’m not sure if I understand your first question but in terms of where this should all live but I recommend looking into boot files

    You’d run:

    $ quasar new boot <file-name>
    

    and from there you can have your socket.io available in all your pages via:

    this.$socket
    

    so in terms of the file structure of quasar src/boot holds all your plugins

    N.B. this is for v1.0



  • Hi @mKomo
    Thank you for your answer. I was guessing boot files was the way to go.

    There are two flavours of socket.io: server and client (socket.io-client). The server part of it commonly can be found in a node.js file (usually called “main.js”, “server.js” and even “index.js”), together with Express or whichever js server is used, being ‘http’ the simplest option.

    Doing a quick research in order to better formulate my first question I just found that nuxt.render, used to create the http-server binded to socket.io is “a middleware for your node.js server.”. So, maybe the question is: how can I use Quasar as a middleware for my node.js server?

    BTW I’m using v1.0, so its all fine about the boot files.

    I hope I managed to make my question more clear.

    Thanks again

    Bests;
    Gil



  • @gil
    Glad to hear!
    Unfortunately I don’t think I can offer sound help for you.
    It might be worth asking what you’re trying to achieve?

    For instance if you are using socket.io to connect to a back-end service or run a socket.io server internally for use with-in your electron app?

    Regards,
    mko



  • Hi @mKomo
    Thank you for sticking with me.
    I’m using socket.io server internally to get and emit OSC messages to others on the web, like a chat, and to other eventual desktop app in the same machine the app would be installed.



  • @gil
    Ah I see (and correct me if I’m wrong)

    So you’re running an electron app that uses socket.io-server.

    And you’ll then be connecting to that local app from other apps and machines on the network

    Figure:

                    Main Electron App (server)
                     /           |            \
                   /             |              \
                 App            App.            App        
    

    I’m not sure what’s an efficient way to go about doing this, as I haven’t played around with electron before, but I’ll look into it further as this sounds pretty interesting

    Feel free to contact me if you come up with a solution and I’ll see what I manage to come up with



  • @mKomo

    That’s it. Actually all apps are clients and servers at the same time as they receive and send messages in real time.

    I’m making it with Electron because web-browsers don’t have the permissions to communicate with other apps in the way I need.

    In the meanwhile I tried to make a boot file with this (now trying vue-socket.io):

    import VueSocketIO from 'vue-socket.io'
    
    export default async ({ Vue }) => {
      Vue.use(new VueSocketIO({
        debug: true,
        connection: 'http://0.0.0.0:8080'
      }))
    }
    

    But hen I’m getting this errors:
    Cross-Origin Read Blocking (CORB) blocked cross-origin response <URL> with MIME type text/html. See <URL> for more details.
    I’m afraid this is not the way to go as I’m trying to do server things on the client side.

    Thank you one more time. If I find a way to solve this I’ll post it here.



  • @gil
    Sounds good, best of luck!



  • Hi friend, I have managed to boot and make my socket available for the entire app only with the client of “socket.io

    considering that you have already launched your socket with node (like the example of socket.io) I show you how I have done it and you can guide you

    we install socket.io
    npm install socket.io-client --save

    we create a boot file for the socket
    quasar new boot socket

    containing the following:

    import io from ‘socket.io-client’;
    export default async ({ Vue}) => {
    Vue.prototype.$mysocket= await io(‘http://100.100.1.205:2222’) //route to the server where you started your socket (and its port)
    }

    In the file “quasar.conf.js” you add the name of your socket in boot and save the changes.
    boot:[‘axios’,‘mysocket’]

    ready!!

    Now you can access your socket anywhere in your app with “this.$mysocket” and use its methods, I recommend you store it in the “data” of the component.

    data(){
    return {
    socket:this.$mysocket
    }
    }



  • I honestly do not know what I am doing wrong, any suggestion would be great please.

    In my boot file:
    
    import io from 'socket.io-client';
    
    export default async ({ Vue }) => {
      Vue.prototype.$mysocket = await io('wss://wwwebsite/testing');
    };
    
    
     data () {
        return {
          socket: this.$mysocket
        };
    },
      mounted () {
        this.socket.on('connect', function () {
          console.log('Your socket is connected!');  //NO EFFECT, NOT WORKING AT ALL, NO CONSOLE LOG
        });
      },
    methods: {
    
        onLogin () { //No effect either.
          this.socket.on({
            "firstname": "firsname", 
            "email": "email",
          })
        },
    

    No errors, nothing happening when I try to connect,

    Any idea why please?

    I am using Quasar v1, thank you.





  • @Gil
    I have a solution with Electron, Socket.io server, and vue-socket-io

    I make my electron application both a server and a client.

    electron-main.js:

    const socket = require('express')()
    const http = require('http').Server(socket)
    const io = require('socket.io')(http)
    const port = process.env.PORT || 3002
    
    socket.get('/', function(req, res){
     res.sendFile(__dirname + '/index.html')
    });
    
    socket.get('/texto/:text', (req, res) => {
     let params = req.params.text
     io.emit('texto', params)
     res.send({mensagem: `Texto: ${params}`})
    })
    
    http.listen(port, function(){
     console.log('WEBSOCKET listening on *:' + port);
    });
    

    in boot websocket-client.js:

    import Vue from 'vue'
    import VueSocketIO from 'vue-socket.io'
    Vue.use(new VueSocketIO({
      debug: true,
      connection: 'http://localhost:3002'
    }))
    
    

    in App.vue:

    <template>
      <div id="q-app">
        <router-view />
      </div>
    </template>
    
    <script>
    export default {
      name: 'App',
      sockets: {
        texto (text) {
          console.log('oi')
          this.activeAlert(text)
        }
      },
      methods: {
        activeAlert(text) {
         alert(text)
        }
      }
    }
    </script>
    

    package.json:

    "dependencies": {
        "@quasar/extras": "^1.0.0",
        "axios": "^0.18.1",
        "express": "^4.15.2",
        "quasar": "^1.0.0",
        "socket.io": "^2.2.0",
        "vue-socket.io": "^3.0.7"
      },
    

    To trigger websocket by sending text through a browser url:

    http: //localhost:3002/texto/test

    It works perfectly.
    Soon I will be providing a source code with this.



  • Problem for me is that I am only using the Web app(not electron) and the websocket is received from a third party(different domain)



  • @metalsadman, thanks, I checked it but it does not help me as I am using Quasar as a Web client with a third party Websocket.



  • Here is how I did it:
    I have a separate folder for my server app, which is an express server using socket.io. It is set to list on port 4000. It is on a separate port from my Quasar app. My server has the following dependencies: express, socket.io, cors, nodemon. My Quasar app also has socket.io as a dependency.

    I created a boot file for my Quasar app: quasar new boot socket.js

    I registered it in the boot section on quasar.conf.js

    My boot file looks like:
    import io from ‘socket.io-client’
    const socket = io.connect(‘http://localhost:4000’);
    export default ({ Vue }) => {
    Vue.prototype.$socket = socket;
    }
    export { socket }

    If you want to use socket in .js files, like for Vuex, you simply: import { socket } from ‘boot/socket’
    If you want to use it within .vue files, simply refer to it as: this.$socket



  • @bambinou socket.io does not work with wss or ws (refer to: https://socket.io/docs/ )
    Your boot file should look like (provided http://website/testing is a valid socket.io server)
    import io from ‘socket.io-client’
    const socket = io.connect(‘http://website/testing’);

    export default ({ Vue }) => {
    Vue.prototype.$socket = socket;
    }
    export { socket }

    That is the end of the file.

    socket is set up and connected to your server before your app starts. There is no need to connect again. If you would like to check for connection, as you did in your example, you may include that in your boot file.
    When you want to use it in a .js file, such as store/index.js, you need to import it:
    import { socket } form ‘/boot/socket’ (if that is what you named your boot file)
    You can then use socket like this: socket.on(‘event’, data => {});

    When you want to use it in a .vue file, you can refer to it as this.$socket like this: this.$socket.emit(‘event’, data);



  • @bambinou Straight from socket.io documentation: What Socket.IO is not
    Socket.IO is NOT a WebSocket implementation. Although Socket.IO indeed uses WebSocket as a transport when possible, it adds some metadata to each packet: the packet type, the namespace and the ack id when a message acknowledgement is needed. That is why a WebSocket client will not be able to successfully connect to a Socket.IO server, and a Socket.IO client will not be able to connect to a WebSocket server either.



  • simple!

    
      1 <template>  
      2   <q-page class="flex flex-center">  
      3     <div>{{message}}</div>                                      
      4   </q-page>                 
      5 </template>  
      6              
      7 <script>  
      8 import io from 'socket.io-client'      
      9 export default {                       
     10   name: 'PageIndex',  
     11   data () {           
     12     return {  
     13       message: '',     
     14       socket: {}  
     15     }  
     16   },  
     17   methods: {  
     18     sendMessage () {                               
     19       this.socket.emit('message', {   
     20         autor: 'quasar-framework',  
     21         text: 'Socket.io on quasar!'                
     22       })  
     23     }  
     24   },  
     25   created () {  
     26     this.socket = io('http://192.168.0.14:3000')  
     27     this.sendMessage()                      
     28     this.socket.on('message', message => {
     29       this.message = message.text
     30     })
     31   }
     32 }          
     33 </script>
    
    

Log in to reply