Node.js的Express应用在Heroku上一直崩溃

7

我在Heroku上推了一个相当简单的node.js express应用程序,但是它无法运行。它立即崩溃了。heroku tail --logs告诉我:

2017-05-23T04:43:08.156660+00:00 app[api]: Scaled to web@1:Free worker@0:Free by user jp@yetie.fr
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

我有一个包含以下内容的Procfile:

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

工作正常,运行如预期。 server.js看起来像这样:

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);
});

在 /testheroku 目录中有一个单独的“hello world”HTML文件。
当我在本地使用 heroku local web 运行它时,它可以正常工作;当我通过连接到 Heroku dyno 并运行 node server.js,然后执行 wget http://localhost:xxxx 时,它也可以正确获取“hello world”HTML文件。
但是,当我尝试访问 Heroku 在构建应用程序时提供给我的 URL 时,我收到了上述崩溃日志。
本地和 Heroku 上的 Node 和 npm 版本相同:
node --version => v6.10.3
npm --version => 3.10.10

我可以提供package.json文件,如果需要的话。但是这个文件相对较长(基于一个更复杂的angular2应用程序),在本地和heroku上都可以正确编译。我能够通过连接dyno来运行node server.js,所以我怀疑问题不应该出现在那里。
我在stackoveflow或其他地方找到的大多数答案都建议使用app.listen(process.env.PORT || 8080)来解决端口问题,我也这样做了。那么我错过了什么?
2个回答

8
请确保您的应用程序可以使用npm start实际启动,并且不会像在Heroku上那样退出。
从日志中可以看出,您的应用程序在启动后约2秒钟后以状态0退出,这通常是因为进程正常退出而没有更多事件侦听器,但有时可能是由其他问题引起的,特别是当自动捕获异常并且您看不到适当的上下文时。
还要确保您的应用程序不依赖于未包含在您的package.json中的任何全局安装的依赖项。确保Heroku执行所需的所有安装和构建步骤。确保您可以将代码复制到新目录中并使用npm install && npm start运行它。
我会更改为:
app.listen(process.env.PORT || 8080, function(){
  console.log("Express server listening on port %d in %s mode", this.address().port, app.settings.env);
});

转换为:

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

为确保其不因您想要访问的所有变量而崩溃。

如果仍然无法正常工作,请查看我在GitHub上的演示:

它还使用express.static,并且已知可以在Heroku上工作 - 使用Heroku部署按钮:

Deploy to Heroku

这个项目对于 Heroku 应用程序的要求甚至比普通应用程序更加严格。

查看该项目中的 package.json、server.js 和 app.json。

你应该能够拥有一个最小的 server.js 文件:

'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}/`);
});

或者不直接使用http模块:
'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}/`);
});

但是同样重要的是,你的package.json文件包括一个启动脚本:

  "scripts": {
    "start": "node server.js"
  },

搞定了!Procfile覆盖了package.json中的启动脚本。从Procfile中删除了web: node server.js这一行,只留下了worker。Heroku仍然发现了两种进程类型:一个是web: npm start,另一个是worker: node workers/match.js。现在即使npm start执行的是与Procfile中删除的那一行完全相同的操作,它也能正常工作了。我的server.js文件保持不变。 - Jean-Philippe

1
另一种方法是:

您可以这样做:

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")
  );
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接