使用app.js还是'npm start'来启动Express.js?

8

我最近在本地服务器上安装了Node.js,当我创建一个“server.js”文件(使用.createServer()方法添加服务器)时,它可以正常加载。

然而,在安装Express.js之后,默认的文件如下:

/bin
/node_modules
/public
/routes
/views
app.js
package.json

在参考了一些文档后,我被指示要进入终端并输入以下命令:

node app.js

当没有任何操作时,命令行会在不到一秒的时间内刷新到下一行,并在访问正确的IP和端口后打开浏览器,但无法连接。

以下是app.js文件中的代码:

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./routes/index');
var users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);
app.use('/users', users);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: err
    });
  });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
        message: err.message,
        error: {}
      });
    });

module.exports = app;

我理解,在文件开头被引用的实际“express”模块是发生魔法的地方,然而,当我运行命令行时:

node app.js

什么都没有发生。但是,如果我调用以下行:

npm start

一切似乎都正常。我希望按照文档进行操作,您有没有任何理由导致 app.js 无法工作?

谢谢。

更新:我的问题与其他已发布的问题太相似了,因此我必须澄清它们之间的确切差异。在另一个问题中,一个人在运行默认的 'app.js' 文件上使用 Supervisor 命令时收到了一个代码编号。

虽然类似,但这个问题应该保留,因为那些使用和我相同方法感到困惑的人将通过使用“node app.js”而不完全了解 Supervisor 实用程序来专注于实际的 'app.js' 文件的身份。

问候。


1
你是在 app.js 所在的文件夹中运行 node app.js 吗? - chriskelly
请参考这个答案了解详情。 - Matthew Bakaitis
@chriskelly,是的,事实上我正在跟随一本Node.js书籍的教程。我已经为我的项目创建了几个服务器,并且使用“http-server”和“npm start”都没有问题,然而,这本书坚持使用根文件夹中的“app.js”,并且似乎没有任何问题。如果可能的话,我想完全按照书中的指示进行操作。 - Mindsect Team
@MatthewBakaitis 我真希望我能为你的答案给予认可,但不幸的是它只是一条评论。非常感谢,这真的解释了很多问题。我没有重新启动服务器的问题,我相信将来我会使用Supervisor。现在,我的主要关注点是牢固掌握知识。再次感谢。(如果您想将您的回复复制粘贴到实际评论中,我可以将其标记为已回答,我会立即处理)。 - Mindsect Team
@chriskelly 说实话,我在理论上一点都不懂,但作为一个已经创建了几个 server.js 文件的人来说,主要区别在于默认的 Express 安装包中包含的 app.js 文件并没有调用 'createServer' 表达式或监听 IP 或端口。可能是因为它是一个基于模板的应用程序,我认为它只是引用了 './bin/www' 目录(这很遗憾,因为我希望我能启动 app.js 文件并立即在浏览器中打开服务器)。 - Mindsect Team
4个回答

17

非常感谢大家的回应,它们真正让我理解了app.js文件在哪里接收功能。感谢Matthew Bakaitis和Bjarni Leifsson的出色贡献。

我要自己回答这个问题的唯一原因是,虽然解释了app.js文件的性质,但如何复制从命令行调用“node app.js”命令以复制我正在遵循的Node.js书籍并未明确说明。

在使用特定短语“以前的express.js版本中的app.js”搜索谷歌后,我偶然发现了Jilles Soeters撰写的一篇好文章,标题为“理解Express app.js”:

http://jilles.me/getting-the-express-app-js/

以下是对我有用的解决方案摘录:

我所涵盖的文件是app.js,这是您Express应用程序的主配置文件。当我第一次打开app.js时,它让我感到困惑。我将告诉你们这里的内容,省去你们去做研究的麻烦。

在做任何其他事情之前,请将以下内容添加到您的app.js中

app.listen(3000);

你需要这样做才能在浏览器中打开你的应用程序。在启动应用程序之后(使用node app.js),请前往127.0.0.1:3000

完成此操作后,我成功运行了该命令。

node app.js

我能够从Express安装的根目录运行此命令,并且可以顺利继续阅读我的Node.js书籍,没有任何其他问题。


我正在阅读《24小时自学Node.js》一书,突然遇到了同样的问题。 - Dr. Xperience

9

这是一个常见的问题,这是因为教程没有清楚地解释当Express生成应用程序时它在做什么。你试图学习新技术,但是教程实际上与你作对。 :(

答案:

当你使用生成器时,package.json会被配置,以便npm start调用./bin/www

那个文件包括app.js,并且在包含后调用app.listen

app.js不会调用app.listen,这就是为什么如果直接调用它,它会退出而没有代码或信息。你必须调用./bin/www或修改app.js...然后就会破坏使用生成器的某些原因。

这里网站上有一个相关问题看到类似的问题,当尝试使用supervisor来保持应用程序运行但一直得到一个exit 0结果。


2
我理解是这样的,我刚开始使用node。
有一个名为bin的文件夹,其中包含www文件。所有的魔法都在这里发生。因此,当你执行node app.js时,它会被执行,但是所有逻辑都在bin/www中。
因此,如果你查看package.json,会看到以下初始化内容:
"scripts": { "start": "node ./bin/www" },
因此,给定这一点,你可以使用start方法来执行脚本,它与./bin/www链接在一起。
如果你查看那个文件,你会发现整个服务器启动逻辑都在那里。
因此,如果你将start更改为其他东西,比如TurnOn,并执行npm TurnOn,它将为你执行./bin/www和整个项目。
项目的结构都是相互关联的,而app.js并不足以启动服务器。
希望这有所帮助。

谢谢你的回答,让我更容易理解了。似乎默认的app.js文件“引用”了文件将被提供的位置,但实际上并没有通过IP和端口调用服务器(因为在app.js中没有createServer方法)。这有点糟糕,但你让它更清晰了。再次感谢。 - Mindsect Team

2
使用Express时,Express实例会为您创建服务器。通常,您的app/index/server.js文件将以以下行开头:
const express = require('express');
const app = express();

这些代码需要使用Express,并在app变量中实例化一个Express实例。然后,Express使用var server = http.createServer(app);为您启动服务器。您只需要确保您的应用程序侦听该服务器(如您所写)。但是,连接的端口可能会有所不同,因此不建议硬编码。相反,应从app变量中检索端口,如下所示:

app.listen(app.get('port'), function(){
    //Something to do when the server starts.
});

此外,在创建自己的app.js文件后,请确保更改您的package.json文件,以通过app.js而不是Express模块启动应用程序。默认情况下,您的package.json可能如下所示:
"scripts": {
 "start": "node ./bin/www"
},

但是在你创建了自己的 app/index/server.js 文件之后,你希望节点在启动时运行该文件:
"scripts": {
 "start": "node app.js"
}

您可以通过在项目目录中编写npm start来启动应用程序。

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