child_process.fork not starting an express server

2019-02-08 20:18发布

I have an electron app where I need not only to run the interface to the user but also start an express server that will serve files for people connected through the network.

I have everything working if I start both electron and the express server normally, but I'm pretty confident that I will need the server running in a different thread to avoid slugish interface and even problems with the server.

For that matter I tried to run my express server using the child_process.fork and it worked when I use npm start, but when I use electron-builder to create an .exe, the installed program doesn't start the express server.

I tried to run my server right away using:

require('child_process').fork('app/server/mainServer.js')

I tried several changes, prefixing the file with __dirname, process.resourcesPath and even hard coding the generated file path; changing the fork options to pass cwd: __dirname, detached: true and stdio: 'ignore'; and even tried using spawn with process.execPath, which will also work with npm start but won't when packaged (it keeps opening new instances of my app, seems obvious after you do hehe)

Note: If I don't fork and require the server script right away, using require('server/mainServer.js') it works on the packaged app, so the problem most like isn't the express itself.

Note 2: I have asar: false to solve other problems, so this is not the problem solver here.

I put up a small git project to show my problem:

https://github.com/victorivens05/electron-fork-error

Any help will be highly appreciated.

1条回答
Evening l夕情丶
2楼-- · 2019-02-08 20:47

With the great help from Samuel Attard (https://github.com/MarshallOfSound) I was able to solve the problem (he solved for me actually)

As he said:

the default electron app will launch the first file path provided to it
so `electron path/to/thing` will work
in a packaged state, that launch logic is not present
it will always run the app you have packaged regardless of the CLI args passed to it
you need to handle the argument manually yourself
and launch that JS file if it's passed in as the 1st argument
The first argument to fork simply calls `process.execPath` with the first
argument being the path provided afaik
The issue is that when packaged Electron apps don't automatically run the
path provided to them
they run the app that is packaged within them

In other words. fork is actually spawn being executed with process.execPath and passing the fork's first argument as the second for spawn.

What happens in a packaged app is that the process.execPath isn't electron but the packaged app itself. So if you try to spawn, the app will be open over and over again.

So, what Samuel suggest was implemented like this:

if (process.argv[1] === '--start-server') {
   require('./server/mainServer.js')
   return
}

require('./local/mainLocal.js')
require('child_process').spawn(process.execPath, ['--start-server'])

That way, the first time the packaged app will be executed, the process.argv[1] will be empty, so the server won't start. It will then execute the electron part (mainLocal in my case) and start the app over, but this time passing the argv. Next time the app starts, it will start the server and stop the execution, so the app won't open again because spawn is never reached.

Huge thanks to Samuel.

查看更多
登录 后发表回答