如何组织大型Node.js项目

85

有什么好方法可以组织大型Node.js项目吗?

例如,使用 express.js 和 socket.io 的应用程序?这将包括应用程序的逻辑结构和文件系统。

目前,我发现自己将大量代码推入单个主js文件中,并将代码放入一个巨大的全局对象中,感觉很不好。


2
有时间读一本书吗? - Straseus
我可能需要购买这本书,谢谢! - Thomas Hunter II
请搜索“JavaScript模块”或“模块化JavaScript” :-) - Sri
1
我已经阅读了Straseus建议的书籍,它给出了许多很好的建议和分析,但我担心它无法很好地转化为使用express构建Node.js应用程序的结构。 PuerkitoBio的下面的回答链接到了一些关于一个良好起点的文件结构的建议;我计划根据需要在该结构的基础上构建。 - Aaron
6个回答

100

一个初学者的例子

我很喜欢 @david-ellis 最初提供的代码,你应该深入研究以理解它,因为这是一个不错的例子。但是,对于想要看到简化版本的初学者来说,我更希望它更加简单明了。接下来是我希望看到的内容。

假设你正在使用 express,并且在 app.js 文件中列出了很多路由。它的内容大致如下:

app.js

// ... startup code omitted above

app.get('/', function(req, res) {
  res.render('index', { title : 'home' });
});
app.get('/contactus', function(req, res) {
  res.render('contactus', { title : 'contact us' });
});
app.get('/anotherpage', function(req, res) {
  res.render('anotherpage', { title : 'another page' });
});
// and so on...

如果你有50个路由,那么这个文件会变得非常混乱。把一些杂乱的内容从app.js文件中移除会很好。

你需要在你的应用程序中创建一个“controllers”文件夹,使你的结构看起来像这样:

app.js
/controllers
在“/controllers”中创建一个名为“index.js”的文件,然后放入以下代码。

/controllers/index.js

module.exports.set = function(app) {
   // copy your routes listed in your app.js directly into here
}

从您的“app.js”文件中剪切并粘贴您的路由列表,并将它们放入“/controllers/index.js”文件中。

在您的app.js文件中,删除您的路由,并执行以下操作。

app.js

// remove your routes and replace with this code
var controllers = require('./controllers');
controllers.set(app);

现在,如果您想要将“/controllers/index.js”文件拆分,让我们再添加一个示例,以便您可以看到Node.js的代码组织方式与俄罗斯套娃非常相似。

在“/controllers”中添加另一个名为“accounts.js”的文件,并将以下内容放入其中。

/controllers/account.js

module.exports.set = function(app) {
    // put more app route listings here
}

现在,在你的"/controllers/index.js"文件中,引用"account.js"。

/controllers/index.js

var account = require('./account.js');

module.exports.set = function(app) {
   // your routes here

   // let "account.js" set other routes
   account.set(app);
}

正如您所想象的那样,您可以将事物分解为更小的部件,并将更多文件夹放入文件夹中,并在需要时使用“require”进行引用。您可以将相同的概念用于“/lib”或库文件。“node_modules”已经在这样做。

这只是 node.js 使编程非常愉快的众多原因之一。

可管理的 Express 4 路由示例

这是我回答了有关与此相关的 express 4 路由的另一篇帖子。

Rest with Express.js nested router


在我看来,更新之前更好,你可以通过实现别名机制来避免为每个控制器命名,其中一个路由进入另一个路由,这也有助于规范URL。 - Timo Huovinen
不要在意规范的URL部分,那只是事后想到的。通过规范的URL,我指的是当用户在地址栏中输入“/example/path/”(或反过来)时,将一个规范的<link>添加到类似“/example/path”的内容中。 - Timo Huovinen
作为程序员,想要这种有组织的层次结构是很自然的,但在实际打开文件或读取代码时并不适用。你最终会得到大量的“index.js”文件,这很快就会让人感到痛苦。 - Abhinav Gujjar
一年后,这篇文章对我非常有价值。我刚开始学习Node.js,准备用它来完成一个周末项目。 - masfenix
@JasonSebring,有太多的信息,而我又是个新手!我现在非常迷茫。作为一名数学研究生,我经常使用matlab/R/mathematica,但我上次接触Web/Desktop框架还停留在.net 2.0时代。 - masfenix

10

几天前,我写了一篇关于这个主题的博客文章,虽然是用法语写的,但我创建了一个GitHub repo(使用英语),以展示我使用的结构的工作示例。

显然,这个问题没有确定的答案,但看看其他人正在做什么是很有趣的,我很愿意听取对此问题的其他观点(这里也讨论过,您可以在那里看到我建议的摘要)。


谢谢你提供的链接,阅读起来很有收获(借助谷歌翻译),我相信我会在当前正在进行的项目的组织设计中采纳你的一些建议。 - Aaron
你能修复这个链接吗? - Yevhenii Herasymchuk

2
与另一篇博客文章类似,我写了一篇专门介绍如何组织Express应用程序的文章。这是我使用了一年半左右的方法。基本上,将应用程序围绕数据实体或任何其他核心元素进行组织。将每个元素的逻辑放置在它们自己的目录中。我尝试从Python中借鉴了很多东西。

http://rycole.com/2013/01/28/organizing-nodejs-express.html


1
他的文章已不再线上,但是Eric Satterwhite的节点系列推荐了下面列出的结构。
# Project 
. 
|-- packages/
|   |-- project-core
|   |   |-- lib/
|   |   |-- commands/
|   |   |-- startup/
|   |   |-- conf/
|   |   |-- test/
|   |   |-- package.json
|   |   |-- README.md
|   |   |-- events.js
|   |   |-- .npmignore
|   |   `-- index.js
|-- package.json
`-- index.js

随着packages/文件夹成为您实现模块化的源。


0

如果你是这个领域的初学者,我建议你看一下那些被开发者喜爱的现有项目。其中一些项目包括:

  • Sails.js - 18k 星。你可以查看我提供的链接,了解他们如何组织 APP 结构。一个很棒的网站对结构中的每个文件夹都有解释。

  • Express.js generator - 800 星。这里有一个伟大而简单的模板,可以开始使用 Express.js 进行工作。在这里,你可以注意到他们如何将路由从应用程序中分离出来。

顺便说一句,许多开发者之前也做过类似的事情,你可以直接 fork 它并进行升级。

  • Kioska。看看他们如何将事件分成不同的文件放在events/文件夹中。

  • Ballons.io 有2.3k颗星。不幸的是,他们把整个套接字服务器都放在一个文件中,但你可以通过node.js和socket.io学习整个应用程序的结构。


0

如果您不介意的话,您可以学习 TypeScript 并尝试使用 https://nestjs.com/

如果您想继续使用 JS,我强烈建议您使用洋葱架构。最佳实践是将业务逻辑、控制器甚至库(它们应该包装在某些类/助手中)分开 - 以防万一,如果您需要迁移到另一个库(不同的 CSV 解析器等)。

使用洋葱架构,您不必关心请求来自哪里,即使添加一些消息代理也不会有太多变化。

还可以尝试这个 https://en.wikipedia.org/wiki/Domain-driven_design

ESLint 可以帮助进行适当的项目组织。


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