如何在Node.js中自动重新加载文件?
编辑:使用http://github.com/isaacs/node-supervisor ; 这是一个老问题,代码示例是使用过时的Node.js API制作的。
关于如何在Node.js中实现文件的自动重装的任何想法? 我厌倦了每次更改文件时重新启动服务器。 显然Node.js的require()
函数不会重新加载文件,如果他们已经被要求,所以我需要做这样的事情:
var sys = require('sys'), http = require('http'), posix = require('posix'), json = require('./json'); var script_name = '/some/path/to/app.js'; this.app = require('./app').app; process.watchFile(script_name, function(curr, prev){ posix.cat(script_name).addCallback(function(content){ process.compile( content, script_name ); }); }); http.createServer(this.app).listen( 8080 );
在app.js文件中我有:
var file = require('./file'); this.app = function(req, res) { file.serveFile( req, res, 'file.js'); }
但是这也是行不通的 – 我在process.compile()
语句中得到一个错误,说'require'没有被定义。 process.compile
正在评估app.js ,但是并不知道node.js全局variables。
一个好的,最新的supervisor
替代者是nodemon
:
监控node.js应用程序中的任何更改,并自动重新启动服务器 – 完美的开发
要使用nodemon
:
$ npm install nodemon -g $ nodemon app.js
我发现一个简单的方法:
delete require.cache['/home/shimin/test2.js']
在Googlesearch中, nodemon首先出现了,而且它似乎有诀窍:
npm install nodemon -g cd whatever_dir_holds_my_app nodemon app.js
如果有人仍然想到这个问题,只想用标准模块来解决这个问题,我举个简单的例子:
var process = require('process'); var cp = require('child_process'); var fs = require('fs'); var server = cp.fork('server.js'); console.log('Server started'); fs.watchFile('server.js', function (event, filename) { server.kill(); console.log('Server stopped'); server = cp.fork('server.js'); console.log('Server started'); }); process.on('SIGINT', function () { server.kill(); fs.unwatchFile('server.js'); process.exit(); });
此示例仅适用于一个文件(server.js),但可以使用文件数组适应多个文件,使用for循环获取所有文件名或通过观察目录:
fs.watch('./', function (event, filename) { // sub directory changes are not seen console.log(`restart server`); server.kill(); server = cp.fork('server.js'); })
这个代码是为Node.js 0.8 API编写的,它不适用于某些特定的需求,但可以在一些简单的应用程序中工作。
更新:这个function是在我的模块simpleR , GitHub回购实施
编辑:我的回答是过时的。 Node.js是一个非常快速的变化技术。
我也想知道重装模块。 我修改了node.js,并在nalply / node上的Github上发布了源代码。 唯一的区别是functionrequire
。 它有一个可选的第二个参数reload
。
require(url, reload)
重新加载当前目录中的app.js
使用
app = require("./app", true);
写这样的东西,你有自动重新加载:
process.watchFile(script_name, function(curr, prev) { module = reload(script_name, true); });
我看到的唯一的问题是variablesmodule
,但我现在正在工作。
这个问题的另一个解决scheme是永远使用
Forever的另一个有用的function是,当任何源文件发生变化时,它可以select性地重启你的应用程序。 这使您无需在每次添加function或修复错误时手动重新启动。 要在此模式下启动Forever,请使用-w标志:
forever -w start server.js
在node.js邮件列表中有一个关于这个主题的最近的线程 。 简短的答案是否定的,它目前不可能自动重新加载所需的文件,但是有几个人开发了添加此function的补丁。
这里是一个关于Hot Reloading for Node的博客文章。 它提供了一个github节点分支 ,您可以使用它来replace您的节点安装以启用热重新加载。
从博客:
var requestHandler = require('./myRequestHandler'); process.watchFile('./myRequestHandler', function () { module.unCacheModule('./myRequestHandler'); requestHandler = require('./myRequestHandler'); } var reqHandlerClosure = function (req, res) { requestHandler.handle(req, res); } http.createServer(reqHandlerClosure).listen(8000);
现在,无论何时修改myRequestHandler.js,上面的代码都会注意到并用新的代码replace本地的requestHandler。 任何现有的请求将继续使用旧的代码,而任何新的传入的请求将使用新的代码。 所有这些都不closures服务器,反弹任何请求,过早地杀死任何请求,甚至依靠智能负载平衡器。
我正在制作一个相当小的节点“东西”,它能够随意加载/卸载模块(所以,也就是说,您可以重新启动应用程序的一部分,而不需要closures整个应用程序)。 我正在合并一个(非常愚蠢的)依赖pipe理,所以如果你想停止一个模块,所有依赖它的模块也将被停止。
到目前为止这么好,但后来我偶然发现如何重新加载模块的问题。 显然,可以从“require”caching中删除模块并完成工作。 由于我并不热衷于直接更改节点源代码,所以我提出了一个非常黑客的问题,那就是:在堆栈中search最后一次调用“require”函数,获取对其“cache”字段的引用然后,删除对节点的引用:
var args = arguments while(!args['1'] || !args['1'].cache) { args = args.callee.caller.arguments } var cache = args['1'].cache util.log('remove cache ' + moduleFullpathAndExt) delete( cache[ moduleFullpathAndExt ] )
实际上更容易:
var deleteCache = function(moduleFullpathAndExt) { delete( require.cache[ moduleFullpathAndExt ] ) }
显然,这工作得很好。 我完全不知道这个论点[1]是什么意思,但是它正在做它的工作。 我相信节点家伙有一天会实现一个重新加载设施,所以我想现在这个解决scheme也是可以接受的。 (顺便说一句,我的“东西”将在这里: https : //github.com/cheng81/wirez ,在几个星期后去那里,你应该看看我在说什么)
node-dev工作得很好。 npm install node-dev
它甚至会在服务器重新加载时给出桌面通知,并且会在消息上给出成功或错误。
在命令行上启动您的应用程序:
node-dev app.js
解决scheme: http : //github.com/shimondoodkin/node-hot-reload
注意你必须自己照顾使用的参考。
这意味着如果你做了:var x = require('foo'); Y = X; Z = x.bar; 并热重新加载它。
这意味着你必须replace存储在x,y和z中的引用。 在热realoadcallback函数中。
有些人混淆热重新加载和自动重新启动我的nodejs-autorestart模块也具有新贵的整合,以启用启动自动启动。 如果你有一个小应用程序自动重启是好的,但是当你有一个大的应用程序热重载更合适。 只是因为热重新加载更快。
另外我喜欢我的节点stream入模块。
没有必要使用nodemon或其他类似的工具。 只需使用您的IDE的function。
IntelliJ WebStorm可能是最好的一个,它具有node.js的热重载function(自动服务器和浏览器重载)。
用这个:
function reload_config(file) { if (!(this instanceof reload_config)) return new reload_config(file); var self = this; self.path = path.resolve(file); fs.watchFile(file, function(curr, prev) { delete require.cache[self.path]; _.extend(self, require(file)); }); _.extend(self, require(file)); }
你现在要做的是:
var config = reload_config("./config");
和configuration将自动重新加载:)
loaddir是我的recursion加载目录的解决scheme。
可以返回
{ 'path/to/file': 'fileContents...' }
或{ path: { to: { file: 'fileContents'} } }
它有callback
,当文件被改变时会被调用。
它处理文件足够大的情况,以防止在完成写操作之前调用watch
。
我在一年左右的时间里一直在项目中使用它,最近又增加了许多的承诺。
帮我试战一下吧!
您可以使用自动重新加载来重新加载模块而不closures服务器。
安装
npm install auto-reload
例
data.json
{ "name" : "Alan" }
test.js
var fs = require('fs'); var reload = require('auto-reload'); var data = reload('./data', 3000); // reload every 3 secs // print data every sec setInterval(function() { console.log(data); }, 1000); // update data.json every 3 secs setInterval(function() { var data = '{ "name":"' + Math.random() + '" }'; fs.writeFile('./data.json', data); }, 3000);
结果:
{ name: 'Alan' } { name: 'Alan' } { name: 'Alan' } { name: 'Alan' } { name: 'Alan' } { name: '0.8272748321760446' } { name: '0.8272748321760446' } { name: '0.8272748321760446' } { name: '0.07935990858823061' } { name: '0.07935990858823061' } { name: '0.07935990858823061' } { name: '0.20851597073487937' } { name: '0.20851597073487937' } { name: '0.20851597073487937' }
另一个简单的解决scheme是使用fs.readFile而不是使用require,您可以保存包含json对象的文本文件,并在服务器上创build一个间隔来重新加载此对象。
优点:
- 不需要使用外部库
- 与生产相关(更改时重新加载configuration文件)
- 容易实施
缺点:
- 你不能重新加载模块 – 只是一个包含键值数据的JSON
对于使用Vagrant和PHPStorm的人来说, 文件监视器是一种更快的方法
-
禁用文件的立即同步,所以你只在保存时运行该命令,然后为* .js文件和工作目录创build一个范围,并添加此命令
stream浪ssh -c“/var/www/gadelkareem.com/forever.sh restart”
forever.sh就是这样
#!/bin/bash cd /var/www/gadelkareem.com/ && forever $1 -l /var/www/gadelkareem.com/.tmp/log/forever.log -a app.js
我最近才想到这个问题,因为通常的嫌疑人并没有使用链接包。 如果您像我一样在开发过程中利用npm link
来有效npm link
理由多个包组成的项目,则重要的是依赖项中发生的更改也会触发重新加载。
在尝试了node-mon和pm2之后,甚至按照他们的说明来另外观察node_modules文件夹,但他们仍然没有select更改。 虽然在这里有一些自定义的解决scheme,但对于这样的事情,单独的包是更清洁的。 我今天遇到了node-dev ,没有任何选项或configuration,它完美的工作。
从自述文件:
与supervisor或nodemon等工具相比,它不会扫描文件系统以查看要监视的文件。 而是挂钩到Node的require()函数中,只查看实际需要的文件。