我想知道一个典型的NodeJS应用程序的结构,因为我阅读和看到的项目越多,我就越困惑,特别是对于这样的问题(或者在我更新这个问题后甚至更多):
以MEAN堆栈为例,据我所知,NodeJS和Express负责服务器部分,提供服务器接口等.MongoDB和Angular非常简单。
但业务逻辑应该去哪里?假设我有一个controller.js
包含一个函数,route.js
文件用这个控制器函数绑定请求。我的问题是:这些文件属于/运行在哪个模块下(Express或NodeJS?)
NodeJS应用的起点在哪里?说index.php
是PHP应用程序的起点,但NodeJS应用程序在哪里?我可以看到所有Nodejs项目都有一个名为server.js
或app.js
等的文件(包含类似module.exports = app;
的内容)但是NodeJS如何知道要查找和执行哪个文件?
我是NodeJS,Express,sequelize.js / Mongoose,Jade / EJS的新手,但想要开始使用NodeJS项目。您能否详细说明每个模块提供的实际功能以及对完整JS堆叠NodeJS应用程序的典型结构的一般介绍?提前谢谢!
答案 0 :(得分:39)
好吧,这是一个非常广泛的问题,我绝对不是专家,但我会在这里尽力而为。
<强> TL; DR 强>
routes
是控制器,用于说明当用户将浏览器导航到应用中的某个路径时要执行的逻辑,包括要呈现的视图以及要向这些视图发送的数据models
只是您应用程序中的数据模型module.exports =
告诉文件它究竟是什么&#34;导出&#34;,这是需要从主应用程序文件执行或访问的代码。require(..)
包含一个模块。您可以在变量上设置它,以便稍后可以调用模块函数,或者只是执行一个函数module.exports
返回。 结合这些技术可以帮助您确定任何应用程序的可靠框架。
长答案
Express为构建Node.js应用程序提供了一个可靠的框架。 Node完全独立于Express,但由于Express的流行程度,它们实际上是相辅相成的。安装完成后,可以使用Express生成脚手架Web项目(带选项),以便您根据自己的需要进行构建。
<强>控制器强>
生成的项目将创建/routes/index.js
,(如果您了解MVC)本质上是您的主控制器。快递中的路线如下:
app.get('/path', function(req, res, next){ .. } );
让我们打破它:我们的应用程序变量(app)被告知在'/path'
的GET请求中执行带有req, res, next
变量的匿名回调函数(分别是请求,响应和回调)。我觉得将此视为自定义事件处理程序很有帮助。
此时需要注意的是,我们也可以使用相同的语法调用app.post
来发布到网址,而不是获取。
在我们的匿名回调中,我们处理任何传入数据并为用户呈现视图。这是我的大多数业务逻辑最终的地方,所以在这里不使用匿名函数实际上是有意义的。以下是仅显示主页的基本回调示例:
app.get('/', function(req, res, next){
//some business logic
res.render('views/home');
});
当用户尝试获取应用程序的索引路径(/
)时,我们只是渲染我们的home
视图,它从项目的根目录存储在views
中}文件夹。
但是,如果我们想模块化这样做,以便我们不会在主app.js
或server.js
中声明我们的所有路线呢?
我们在模块中使用module.exports = ..
来告诉我们的服务器究竟包含哪些内容。在我的控制器中,我导出一个函数,它将应用程序作为参数并使用它来定义我们的路由,如下所示:
控制器/ user.js的
module.exports = function(app){
app.get('/users', function(req, res){
var users = req.db.collection('users').find();
if (!users) {
console.log("no users found");
res.redirect('/');
} else {
res.render('users/index', {users : users});
}
});
};
不要担心req.db
代码,我会将数据库附加到我的应用程序中的请求,但默认情况下不会这样做。只需了解我已获得“用户”列表即可。在这里,如果没有任何内容,则将用户重定向到我的应用程序的索引。
<强>模型强>
Mongoose为我们提供了编写模型的绝佳界面。使用猫鼬,写作模型是一个三步过程:
以下是User
模型的示例:
<强>模型/ user.js的强>
var mongoose = require('mongoose'),
userSchema = new mongoose.Schema({
name: { type: String, required: true },
joinDate: {type: Date, default: date.now }
}),
User = mongoose.model('user', userSchema);
module.exports = user;
服务器应用
module.exports
用于帮助我们为代码库定义一些模块性。当我们运行节点应用程序时,我们最终会运行一个JavaScript文件(您已经看到该文件包含server.js
或app.js
)。
为了防止此文件因多个模型和路由而变得太大,我们使用require(module)
来包含来自其他JS文件的代码。在我们的例子中,module
将是我们想要的模块的路径。如果您有以下doc结构:
| Controllers
- User.js
| Models
- User.js
| Views
app.js
要包含app.js
的用户控制器,您需要写:require('./Controllers/User')
。由于我们的控制器模块只是导出函数,我们可以在require语句之后立即调用该函数,只需在末尾添加括号(无论需要什么参数)。包括我的控制器看起来像这样:
require('./Controllers/User')(app)
我传递了实际的应用,因为我的模块(下面)只是导出一个功能,可以将业务逻辑添加到我应用的路由中。这只需要调用并且从不使用,因此我不会将我的控制器捕获为变量,以便稍后调用方法。
包含模型有点不同,因为我们可能希望执行模型定义的某些操作。我们可以通过稍微改变我们的需求代码来实现这一点:
var User = require('./Models/User');
现在我们可以随时调用User模型的方法。 Mongoose免费提供了许多基本功能:
User.find({}, function(err, users){ .. });
上面的函数将找到我们所有的用户,然后执行一个潜在的err
的匿名函数(如果没有问题则为null),然后是JSON格式的用户列表。非常漂亮。
结合所有这些概念是如何使用Express和Node.js创建基本Web应用程序。如果有任何我可以澄清的关于我如何使用Express的内容,请在评论中告诉我。这是非常表面层面的知识,我建议深入研究文档并查看插件以扩展应用程序的功能。祝你好运!