Spawn a child process in Electron

This answer would suit your app if it is a Portable .exe. I haven't myself worked with an installable one so don't know much about that.

Creating a child process while doing development is really easy. Simplest is using fork() from Node's child_process(Though we can use any of spawn/exec/execFile... etc depending on what we want).

The tough part comes when we pack the application as an Executable which contains the packaged files as "app.asar".

The key point is, do you understand what "app.asar" is? "app.asar" on a normal glance will look like a normal bundled file but it actually is a Virtual Directory, this means you can traverse inside it as you would with any other directory, maybe just consider it as a directory name. If you would do __dirname under the main process of the electron code you would see the location as '/path/to/app.asar'.

How do you see what is inside "app.asar"? - reference

fs.readdirSync('/path/to/app.asar')

Answer

You need to bundle/copy the file (the file which will run on a separate process, say filename is: "child.process.js") separately into the folder from which your packager (like: electron-builder) is creating the EXE. Let's say you package everything under a "dist" folder, then this dist folder should have the file child.process.js. Now this "dist" folder itself will become "app.asar".

When you specify the path of child.process.js for the fork() and if the file "child.process.js" lies directly inside dist, give it like:

fork(path.join(__dirname, 'child.process.js'))

If there it present under subdirectories, then give the appropriate path.

The interesting thing is, the above code works both while using it as a portable EXE and while development(If you bundle all the main process files into one file.)



It took me 3 days to figure this out. How I did my debugging while testing the EXE? I used fs to write to files and later opened them and read their contents. I only realized the solution when I printed the output of fs.readdirSync('/path/to/app.asar'). The funny thing was I had two dist folders and I was packaging my child file for local development dist but wasn't doing it for the dist from which I was packaging the App.

Hope this helps somebody!


Also, you can fork nodejs file inside electron process:

let serverProc = require('child_process').fork(
  require.resolve('./server.js'),
  ['--key', 'value'], // pass to process.argv into child
  {
    // options
  }
)
serverProc.on('exit', (code, sig) => {
  // finishing
})
serverProc.on('error', (error) => {
  // error handling
})

Finally, I've solved it.

The way I solved this is doing exactly the reverse, NodeJS is available on the production machines so I just wrote a start.js script that basically spawn a child process to run Electron and on the parent process I'm running this long running task and finally I'm using IPC to communicate between the two processes.


If you are compiling Electron with the --asar flag, based on the docs that would be a problem.

There's also this issue where you can not have the stdio attached to the parent. So assuming having a detached stdio is not a deal-breaker, you can try { stdio: 'ignore' }.

Tags:

Electron