问题描述
我正在构建一个现在相当大的nodejs应用程序.为了避免单片节点应用程序,我采用了更加模块化的系统的体系结构路线,该体系结构将几个组件分解为单独的npm模块.这些使用npm发布并安装在相关模块中.我大约有6个不同的模块(我想进一步介绍),现在管理包变得很困难.
I am building a nodejs application that is fairly large now. In an attempt to avoid a monolithic node application I have gone down the architectural route of a more modular system breaking out several components into separate npm modules. These are published using npm and installed in the dependent modules. I have about 6 different modules (which I would want to break out in to more) and now it has become difficult to manage the packages.
问题是:
- 存在嵌套依赖性,因此如果我更改模块A而模块B依赖于模块A而模块C依赖于模块B,那么当我更新模块AI时需要发布它的新版本,这意味着我需要更新它在模块B中,这意味着我还需要发布该模块,然后最后我需要在模块A中安装该新版本...您可以看到哪里可能会很痛苦.此外,所有package.json中的版本更新都是手动操作,因此容易出错,并且等待每次发布都很耗时.
- 模块可以共享npm依赖性,因此有时在更新软件包时会发生冲突.模块越多,冲突的可能性就越高.
好处是我们拥有一个非常模块化的系统,在该系统中,可以轻松地重用库,并且由于没有任何循环依赖性,因此强制执行的模块层次清晰.
The benefits are that we have a very modular system where libraries can be reused easily and there is a clear hierarchy of modules enforced as there can't be any circular dependencies.
可能的解决方案是:
-
Monolith -在单个存储库中作为单个应用程序管理依赖项,而每个模块都只是一个服务.这意味着只需要一次更新,所有模块api都将同步.但是,在代码中引用库可能会有些麻烦(因为我认为必须相对于本地文件进行引用),我不确定如何在模块之间强制执行结构层次结构,并且代码重用将如何在存储库外使用模块会更加困难.
Monolith - To manage the dependencies as a single app in a single repository with each module just becoming a services. This means that only one update is necessary and all the module apis will be in sync. However, referencing the libraries in the code might be a bit of a pain (as I believe they will have to be referenced relative to the local file), I am not sure how a structural hierarchy between the modules can be enforced and code reuse will be harder with modules outside the repository.
微服务-使每个模块成为微服务.这保留了模块化系统的所有优点,但我担心它会增加构建的复杂性,并且管理所有服务本身将成为一项全职工作.
Microservices - To make each module a micro service. This maintains all the benefits of the modular system, but I am concerned that it will add a lot of complexity to the build and managing all the services will become a full time job in itself.
继续前进-设法保留当前体系结构,但消除了推送更新等麻烦.也许脚本可以更新版本并收缩包装以确保正确的依赖关系.我认为这既困难又有可能导致它成为一个不同种类的整体系统.
Keep going - Work out a way to keep the current architecture but remove the trouble of pushing updates etc. Maybe scripts to update versions and shrinkwrap to ensure correct dependencies. I think this would both be difficult and would potentially lead it to being a monolithic system of a different variety.
对我来说,选项1似乎是最易于管理的,但我不想失去模块化结构.
Option 1 seems the most manageable to me but I don't want to lose the modular structure if I don't have to.
这是一个相当广泛的问题,但是任何建议/建议/评论都将非常有帮助.
This is quite a broad question, but any suggestions/advice/comments would be really helpful.
谢谢
推荐答案
我建议使用解决方案2.
I'd recommend going for solution 2.
- 在小模块中分解所有代码.
- 使用事件发射器实现松散耦合.
- 除非将每个模块作为单独的npm包存储在您的应用程序之外,否则它们没有任何附加价值.
您描述的两个问题仅是由于每个模块都独立存储为npm软件包而引起的.
The two problems you have described are simply caused by the fact that each module is independently stored as an npm package.
- 解决了问题1,因为您不再需要在
package.json
中管理npm软件包. - 问题2已解决,因为您只有一个
package.json
管理所有依赖项 - 由于使用了单独的node.js模块,您仍然拥有干净的模块化结构.
- Problem 1 is solved as you don't need to manage npm packages in
package.json
anymore. - Problem 2 is solved as you only have one
package.json
managing all the dependencies - You still have a clean modular structure thanks to usage of separate node.js modules.
几个月前,我使用这些原理重构了一个单体的node.js应用程序,它确实简化了维护,并且没有增加构建过程的开销.
A few months ago, I refactored a monolithic node.js app using these principles, and it really eased the maintenance, and didn't add overhead to the build process.
模式如下:
主模块是app.js
var sys = require('sys')
, events = require('events')
, UserModel = require('./model/user') // this is a microservice taking care of managing user data
, Logic = require('./controller/logic') // this is another microservice doing some work
var App = function (server, app) {
this.controller = (
logic: new Logic(this) // "this" is the app instance, it's passed to all microservices, which will benefit from the access to event emitter...
}
this.model = {
new UserModel(this)
}
// ...
}
sys.inherits(App, events.EventEmitter)
module.exports = App
微服务看起来像这样:
/**
* Logic functions
*
* this controller does ...
*
* @constructor
*
*/
function Logic(app) {
/****************************************
*
* Private methods
*
****************************************/
/**
* this is a private function in the controller
*
* @private
*/
function computeSomething () {
var res = 3
app.emit('computed', res) // emit event, that can be liseted to by some other modules
return res
}
/****************************************
*
* Public methods
*
****************************************/
/**
*
* This function can be called directly by the other modules using "app.controller.logic.work()"
*
*/
this.work = function () {
return 'result is ' + computeSomething()
}
/****************************************
*
* Event listeners
*
****************************************/
/**
* listener: event from the app - loose-coupling magic happens thanks to this. Recommended over public functions.
*
* @private
*/
app.on('data-ready', this.work)
}
module.exports = Logic
这篇关于节点模块化架构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!