nuxt-community / electron-template

Electron starter with nuxt.js
MIT License
251 stars 31 forks source link

How to communicate between main process and renderer processes? #4

Closed PeterKnight closed 7 years ago

PeterKnight commented 7 years ago

I'm trying to pass on a message from the main process to a vue component, but requiring electron inside a vue component doesn't work (Can't resolve 'fs' in...electron error). Looking at https://github.com/nuxt/electron/issues/3 it seems we can't include most packages, such as electron itself inside a vue component. So how is it done?

This question is available on Nuxt.js community (#c12)
Kylart commented 7 years ago

I had kind of the same problem (which I described in #3 ) and it got solved it by defining routes to call from a vue component (actually from the store but kinda the same) with axios.

@ausir0726 made a repo to explain this to me that you can find here.

It looks like this.

// main.js
const nuxt = new Nuxt(config)

// You can set this function in another file and call it but you have to call it there (I put mine in assets folder)
const route = (req,res) => {
  const url = new URL(req.url);
  if(url.pathname == '/<the-path-you-like>'){
    const query = querystring.parse(url.query.replace('?',''));
    const <variable> = query.<variable>

    console.log('Received')

    // Do your work here

    const result = {
      <key>: <value>
    }

    res.writeHead(200, {"Content-Type": "application/json"})  // if you want JSON ofc
    res.write(JSON.stringify(result))
    res.end()
  }else{
    return nuxt.render(req,res)
  }
};
const server = http.createServer(route)
// Client-side
import axios from 'axios'

(...)

export default {
  data() { return {
     msg: 'Hello world'
   } 
  },
  methods: {
     callRoute() {
        const { data } = axios.get(`/<the-path-you-set>?<variable>=${this.msg}`)
        console.log(data)
     }
  }
}

(...)

This method has several problems though..

  1. You must restart your app everytime you change something.
  2. You might have to create a lot of routes. Which is not a real problem.

I hope it helps.

PeterKnight commented 7 years ago

Thank you @Kylart, that's a useful approach! Very new to nuxt.js and electron so I'm still learning.

In the use case I'm trying to get working the message is triggered in main.js and I want to let my vue component know once it's triggered. Creating a route in main js implies the component has to poll it, which doesn't work as well for what I'm trying to do.

I'm trying to let the component know when the window becomes focused so I can trigger the focus inside an editor. I started out with this in main.js. Can't import electron inside the vue component it seems so it can't listen for messages through a conventional way...not sure if there is another way?

// in main.js
win.on('focus', (event) => {
        event.sender.send('asynchronous-reply', 'is-focused')
})
PeterKnight commented 7 years ago

This is relevant perhaps https://github.com/webpack/webpack/issues/3012

Not sure where to tweak the webpack config here though....webpack is also a first for me.

detrohutt commented 7 years ago

@PeterKnight Good find. Try editing your nuxt.config.js file to look like this:

module.exports = {
  /*
  ** Electron Settings
  */
  electron: {
    width: 1024,
    height: 768
  },
  build: {
    extend (config, { isClient }) {
      // Extend only webpack config for client-bundle
      if (isClient) {
        config.target = 'electron-main'
      }
    }
  }
}

Let me know if that gets you any closer to it working.

PeterKnight commented 7 years ago

@detrohutt

Thank you!

Setting the target to electron-main prevented it from loading, but setting the target to electron-renderer works!! Very happy with this!

This is what the build config looks like for me:

build: {
        extend (config, { isClient }) {
            // Extend only webpack config for client-bundle
            if (isClient) {
                config.target = 'electron-renderer'
            }
        }
    }