Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node.js express app keep crashing on heroku

I pushed a fairly simple node.js express app on heroku and can't make it works. It immeadiately crash. heroku tail --logs gives me :

2017-05-23T04:43:08.156660+00:00 app[api]: Scaled to web@1:Free worker@0:Free by user [email protected]
2017-05-23T04:43:24.388293+00:00 heroku[web.1]: Starting process with command `: node server.js`
2017-05-23T04:43:26.207926+00:00 heroku[web.1]: Process exited with status 0
2017-05-23T04:43:26.220393+00:00 heroku[web.1]: State changed from starting to crashed
2017-05-23T04:43:26.221461+00:00 heroku[web.1]: State changed from crashed to starting
2017-05-23T04:43:43.343050+00:00 heroku[web.1]: Starting process with command `: node server.js`
2017-05-23T04:43:44.751608+00:00 heroku[web.1]: Process exited with status 0
2017-05-23T04:43:44.762870+00:00 heroku[web.1]: State changed from starting to crashed
2017-05-23T04:43:46.400260+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=yetie.herokuapp.com request_id=d7913d1e-64ab-497b-a59d-fda9454d6e69 fwd="81.56.46.53" dyno= connect= service= status=503 bytes= protocol=https
2017-05-23T04:43:46.899099+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/favicon.ico" host=yetie.herokuapp.com request_id=1fdc61fb-eebe-40a2-8b0a-a71b09f7ff10 fwd="81.56.46.53" dyno= connect= service= status=503 bytes= protocol=https

I have a Procfile that contains :

web : node server.js
worker: node workers/match.js

worker, run as expected. server.js looks like this :

const express = require('express');
const app = express();

app.use(express.static(__dirname + '/testheroku'));

app.listen(process.env.PORT || 8080, function(){
  console.log("Express server listening on port %d in %s mode", this.address().port, app.settings.env);
});

In /testheroku dir there is a single "hello world" html file.

When I run it locally with heroku local web it works, when I run it by connecting to heroku dyno with heroku run bash then node server.js and then doing a wget http://localhost:xxxx it properly get the "hello world" html file.

But when I try to access the url heroku gives to me when I build the app, I get the above crash logs.

Node and npm versions are the same locally and on heroku :

node --version => v6.10.3
npm --version => 3.10.10

I may include the package.json file if requested, but it's fairly long (based on a more complex angular2 app) and it compiles properly both localy and on heroku. And as I manage to run node server.js by connecting to the dyno thru bash, I doubt the issue should be there.

Most answers I found on stackoveflow or elswere suggest a port issue and to use the app.listen(process.env.PORT || 8080) trick, which I did. So what am I missing here ?

like image 576
Jean-Philippe Avatar asked May 23 '17 13:05

Jean-Philippe


2 Answers

Make sure that you can actually start your app with npm start and that it doesn't exit, as it seems to do on Heroku.

From the logs it seems that your app exits after about 2 seconds from starting with a status 0 which is usually the case if the process exits normally because there are no more event listeners but sometimes it can be caused by other problems, especially when your exceptions are automatically caught and you don't see a proper context.

Also make sure that your app doesn't depend on any globally installed dependencies that are not included in your package.json. Make sure that Heroku does all of the installation and building steps required. Make sure that you can copy the code into a fresh directory and run it with npm install && npm start.

I would change this:

app.listen(process.env.PORT || 8080, function(){
  console.log("Express server listening on port %d in %s mode", this.address().port, app.settings.env);
});

to this:

const port = process.env.PORT || 8080;
app.listen(port, () => {
  console.log('Express server listening on port', port)
});

to make sure that it's not crashing because of all of the variables that you want to access.

If it still doesn't work take a look at my demo on GitHub:

  • https://github.com/rsp/node-live-color

It also uses express.static and it is known to work on Heroku - with a deploy to Heroku button:

Deploy to Heroku

which has even stricter requirements than normal Heroku apps.

Take a look at the package.json, server.js and app.json in that project.

You should be able to have a minimal server.js file:

'use strict';

const path = require('path');
const express = require('express');
const http = require('http');

const app = express();
const server = http.Server(app);

const port = process.env.PORT || 8080;

app.use('/', express.static(path.join(__dirname, 'testheroku')));

server.listen(port, () => {
  console.log(`Listening on http://localhost:${port}/`);
});

or without a direct http module usage:

'use strict';

const path = require('path');
const app = require('express')();

const port = process.env.PORT || 8080;

app.use('/', express.static(path.join(__dirname, 'testheroku')));

app.listen(port, () => {
  console.log(`Listening on http://localhost:${port}/`);
});

but it's also important that your package.json includes a start script:

  "scripts": {
    "start": "node server.js"
  },
like image 196
rsp Avatar answered Oct 28 '22 04:10

rsp


Another way you could do this is:

app.set("port", process.env.PORT || 3000);
app.set("host", process.env.HOST || "localhost");

app.listen(app.get("port"), function() {
  console.log(
   "%s server listening at http://%s:%s",
    process.env.NODE_ENV,
   app.get("host"),
   app.get("port")
  );
});
like image 1
error404 Avatar answered Oct 28 '22 02:10

error404