diegohaz / arc

React starter kit based on Atomic Design
https://arc.js.org
2.92k stars 292 forks source link

[redux-ssr] Windows 10 Hot reloading #248

Closed justinmasse closed 7 years ago

justinmasse commented 7 years ago

When hot reloading on windows 10 I get this slightly annoying error message to let me know that there is something already running on port 3000.

Perhaps there is a way to silence this?

> arc@0.1.0 start C:\Users\jmasse\Documents\sites\arc-redux-ssr
> node .

Error: listen EADDRINUSE :::3000
    at Object.exports._errnoException (util.js:953:11)
    at exports._exceptionWithHostPort (util.js:976:20)
    at Server._listen2 (net.js:1253:14)
    at listen (net.js:1289:10)
    at Server.listen (net.js:1385:5)
    at EventEmitter.listen (C:\Users\jmasse\Documents\sites\arc-redux-ssr\node_modules\express\lib\application.js:618:24)
    at Object.module.exports.Object.defineProperty.value (C:\Users\jmasse\Documents\sites\arc-redux-ssr\dist\webpack:\src\server.js:97:5)
    at __webpack_require__ (C:\Users\jmasse\Documents\sites\arc-redux-ssr\dist\webpack:\webpack\bootstrap 38a81447761e40ac2efa:19:1)
    at Object.module.exports.Object.defineProperty.value (C:\Users\jmasse\Documents\sites\arc-redux-ssr\dist\server.js:1573:18)
    at __webpack_require__ (C:\Users\jmasse\Documents\sites\arc-redux-ssr\dist\webpack:\webpack\bootstrap 38a81447761e40ac2efa:19:1)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! arc@0.1.0 start: `node .`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the arc@0.1.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\jmasse\AppData\Roaming\npm-cache\_logs\2017-05-12T21_37_45_063Z-debug.log
PB-RHamilton commented 7 years ago

I am on Windows 8 and am also getting this error. It seems to be the result of the webpack-spawn-plugin calling npm start every time anything the server.js file references changes (which includes all of the components, containers, store, etc.). npm start runs node . which refers to ./dist/server.js - the webpack compiled version of server.js.

The problem seems to arise with the original node process running ./dist/server.js not being killed before running it again.

You also cannot catch this error anywhere. The following edit still causes the new node . process to fail:

try {
  console.log(`listen to port ${port}`)
  app.listen(port, (error) => {
    const boldBlue = text => `\u001b[1m\u001b[34m${text}\u001b[39m\u001b[22m`
    if (error) {
      console.error('in app.listen', error)
    } else {
      console.info(`Server is running at ${boldBlue(`http://${host}:${port}${basename}/`)}`)
    }
  })
} catch (err) {
  console.error('outer catch', err)
}
diegohaz commented 7 years ago

webpack-spawn-plugin uses fkill to kill the previous process: https://github.com/diegohaz/webpack-spawn-plugin/blob/master/src/index.js#L26

Maybe fkill doesn't work on Windows? Does anyone know a cross-platform solution? I'm not on Windows, so I can't try this. :(

diegohaz commented 7 years ago

Could you try to debug things on node_modules/webpack-spawn-plugin/dist/index.js while running npm run dev?

PB-RHamilton commented 7 years ago

Looking further into this I get the following error from fkill:

{ AggregateError:
    Error: Killing process 17304 failed: ERROR: The process with PID 17304 could not be terminated.
    Reason: This process can only be terminated forcefully (with /F option).
        at Promise.all.then (C:/Users/rhamilton/dev/pblead3/node_modules/fkill/index.js:41:10)
    at Promise.all.then (C:\Users\rhamilton\dev\pblead3\node_modules\fkill\index.js:41:10)
    at process._tickCallback (internal/process/next_tick.js:109:7) name: 'AggregateError' }

When fkill is called with { force: true } passed as the second parameter it reports success (doesn't enter the .catch of the returned promise) but the new process still crashes with the Error: listen EADDRINUSE :::3000 error.

This still happens when I add a delay of 1 second after reported success from the fkill promise like this:

promise.then(() => new Promise(res => setTimeout(res, 1000)))
      .then(() => {
        console.log('fkill success')
        return doSpawn();
      }).catch((err) => {
        console.error(err);
        return doSpawn();
      });
PB-RHamilton commented 7 years ago

I thought for a while it might be because I was running yarn dev instead of npm run dev but it made no difference.

PB-RHamilton commented 7 years ago

Replacing fkill with a promise that calls process.kill(pid, 'SIGKILL') also does not resolve the issue. Yay windows!

PB-RHamilton commented 7 years ago

This is a limitation of the fkill package. On windows it uses the taskkill package to kill the process but fkill will not pass the tree option to kill all children of the process. It effectively orphans the child node processes.

Changing const promise = this.pid ? fkill(this.pid) : Promise.resolve() to const promise = this.pid ? taskkill(this.pid, { force: true, tree: true }) : Promise.resolve() resolves this on windows (but only windows).

The tree option in taskkill kills all child processes along with the one associated with the pid.

Here is how fkill calls taskkill excluding any options other than force:

function win(input, opts) {
    return taskkill(input, {
        force: opts.force
    });
}

In the following pic 1 is the process being killed and 2 is the process that is listening on the port. processes

diegohaz commented 7 years ago

@PB-RHamilton @justinmasse I just updated webpack-spawn-plugin. Could you please run npm update (or yarn upgrade) to see if that works?

diegohaz commented 7 years ago

Since nobody else has reported it, I will consider this fixed. If the problem persists I reopen it.