Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/34.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 运行时添加/删除/重新加载NodeJS需要无需重新启动服务器(也没有nodemon)_Javascript_Node.js_Module_Content Management System - Fatal编程技术网

Javascript 运行时添加/删除/重新加载NodeJS需要无需重新启动服务器(也没有nodemon)

Javascript 运行时添加/删除/重新加载NodeJS需要无需重新启动服务器(也没有nodemon),javascript,node.js,module,content-management-system,Javascript,Node.js,Module,Content Management System,我有一个工作项目,我基本上是创建一种CMS形式,随着时间的推移,我们将添加应用程序 我们面临的问题是如何在服务器中加载这些应用程序,并在运行时进行更具体的修改 我们之所以需要这种形式的热加载,是因为我们不希望服务器在进行更改时重新启动,更具体地说,我们希望通过管理面板添加新的应用程序 Nodemon是一个非常有用的开发工具,但对于我们的生产环境,我们希望能够替换现有的应用程序或模块/插件(如果您愿意),而无需重新启动服务器(无论是手动还是通过Nodemon),服务器需要一直运行 您可以将其与CM

我有一个工作项目,我基本上是创建一种CMS形式,随着时间的推移,我们将添加应用程序

我们面临的问题是如何在服务器中加载这些应用程序,并在运行时进行更具体的修改

我们之所以需要这种形式的热加载,是因为我们不希望服务器在进行更改时重新启动,更具体地说,我们希望通过管理面板添加新的应用程序

Nodemon是一个非常有用的开发工具,但对于我们的生产环境,我们希望能够替换现有的应用程序或模块/插件(如果您愿意),而无需重新启动服务器(无论是手动还是通过Nodemon),服务器需要一直运行

您可以将其与CMS(如Drupal、Yoomla或Wordpress)进行比较,但出于我们的需要,出于许多原因,我们认为Node是更好的方式

在代码方面,我正在寻找类似的东西,但这会起作用:

让应用程序=[] //通过调用appropiate类方法的web界面添加新应用程序,在该方法中运行以下代码: 应用程序。pushrequire'path/to/application'; //修改应用程序时: 应用指数,1; applications.push'path/to/application'; 但我需要对上述应用程序的现有实例进行调整

例如:

//文件位置:./Applications/application/index.js 班级申请{ 问候{ console.logHello; } } module.exports=应用程序; 应用程序加载程序将加载到所述应用程序中:

类加载器{ 建造师{ this.List=新对象; } Addappname{ this.List[appname]=require`./Applications/${appname}/index`; } Removeappname{ 删除require.cache[require.resolve`./Applications/${appname}/index`] 删除此。列表[appname]; } 重新加载AppName{ 此.Removeappname; 这个.Addappname; } } 运行代码:

const AppLoader=需要“AppLoader”; const applications=新的应用程序加载程序; 应用程序。添加“应用程序”;//添加上面创建的应用程序 var app=新应用程序。列表['application']; app.greet; //对应用程序文件进行了更改,.greet现在输出Hello World而不是Hello //通过fs.watch或手动触发器执行某些操作,以知道它必须重新加载 应用程序。重新加载“应用程序”; app.greet; 预期的行为是:

Hello
Hello World
事实上,我得到了:

Hello
Hello
如果有人能帮我找到一种方法,在这样的应用程序中动态加载,同时在运行时删除/重新加载它们,我将不胜感激


编辑:如果有一种方法可以在不使用require的情况下运行我的应用程序代码,从而允许动态加载/重新加载/删除,那么这也是一种受欢迎的解决方案

好的,多亏了@jfriend00,我意识到我需要用我的代码修复其他东西,所以他的评论对其他人仍然有用。至于我卸载所需模块或在不重启服务器的情况下重新加载它们的问题,我找到了一种相对优雅的方法。 首先,让我向您展示我所有的测试类和app.js,我将解释我做了什么以及它是如何工作的

Class.js:

严格使用; 班级{ 建造师{ //此.file将在运行时后放入注释中,而此.Output=Hey将取消注释以更改源文件。 var日期=新日期 this.Output=date.getHours+:+date.getMinutes+:+date.getSeconds+.+date.getmillizes; this.file=global.require.fs.readFileSync'/file.mov'; //this.Output=Hey; } } module.exports=类; app.js:

"严格使用",; global.require={ fs:require'fs' }; 常数arr=[]; const mod='./class.js' 让Class=[null]; 类[0]=所需模板; 设c=[]; c、 新类[0]; console.logc[0]。输出; console.logprocess.memoryUsage; 设置超时=>{ 删除require.cache[require.resolvemod]; 删除类[0]; 类[0]=所需模板; console.logClass 删除c[0]; c[0]=新类[0]; console.logc[0]。输出; console.logprocess.memoryUsage; }, 10000; 现在让我在这里解释一下,请注意,这是测试代码,所以命名很糟糕

我就是这样去上班的:

第一步 我需要一种方法来分离所需的模块,如fs、websocket、express等。这样就不会弄乱整个代码的delete require\u缓存部分,我的解决方案是使这些模块成为全局所需:

global.required={ fs:require'fs' } 步骤2 找到一种确保垃圾收集器删除卸载代码的方法,我通过将requires和class声明放在一个变量中实现了这一点,这样我就可以在Node/Javascript中使用delete功能。我在测试代码中使用了let,因为我事先测试了另一种方法, 还没有测试const是否还能工作。 在本例中,我还创建了一个变量,其中包含文件的路径字符串。'/Class.js',但为了下面的解释,我将按原样编写它

let Class=[null]//这声明了一个具有索引“0”的数组 类[0]=需要“/类”; 设c=[new Class[0]]//这声明了一个数组,该数组在索引“0”中实例化了该类 至于垃圾收集,我只需要做以下几点:

删除类[0]; 删除c[0]; 在这之后,我能够重新声明所需的类,并随后声明类本身,并保持代码正常工作,而无需重新启动

请记住,在实际项目中实现his需要大量工作,但您可以通过向类添加unload方法来卸载底层自定义类,从而将其拆分。但我的初步测试表明,这就像一个魅力

编辑:我觉得需要注意的是,如果没有jfriend00的评论,我永远不会想出这个解决方案

输出 项目开始时,它会输出当前时间和流程。memoryUsage

在10秒钟的等待过程中,我将Class.js文件更改为不读取file.mov,并说Hey而不是time,在10秒超时后,这是输出:

Hey
{ rss: 48439296,
  heapTotal: 7585792,
  heapUsed: 4435408,
  external: 8680 }

从技术上讲,您无法卸载node.js中的代码。您可以忘记它,将其保留在内存中,并根据需要加载替换代码。以前加载的模块中的任何状态都将属于以前加载的模块,除非您开发了一些编码机制来手动提取以前的状态并将其传递给新加载的代码。我不知道这些动态加载的应用程序是什么,但如果您将它们放在各自的进程中,然后您可以终止之前的进程,并将新代码加载到新的进程中。这将彻底清除以前版本的代码。当然,您必须使用多种形式的进程间通信中的一种来与它通信。通过将代码手动读入内存并使用eval,代码可以无需运行,虽然我不确定它是否真的比使用require更能为您带来任何好处。如果它满足您的需求,我会首先使用它,因为它可能是最简单的。如果您将每个应用程序放在自己的子进程中,那么您可以向该进程发送一条消息,告诉它清理并退出。如果它在超时后拒绝,那么您可以终止子进程。仅供参考,将每个应用程序放在其自己的子进程中也可以防止它们使用行为不良的代码关闭您的服务器。
Hey
{ rss: 48439296,
  heapTotal: 7585792,
  heapUsed: 4435408,
  external: 8680 }