node.js require()缓存自动无效

时间:2013-12-18 17:31:26

标签: node.js

我知道可以使用delete清除require缓存,但是每次我使用外部模块时都没有运行删除,有没有人做过检测文件被更改的方法(例如通过修改时间? )如果缓存有变化,只会使缓存无效?即而不是:

var ext = require(filename);
ext.do_stuff();
delete require.cache[require.resolve(filename)];

有些事情:

if(PSEUDO_is_file_changed(filename)){
    delete require.cache[require.resolve(filename)];
}
var ext = require(filename);
ext.do_stuff();

我正在考虑fs.stat的内容,只是跟踪mtime,但文件名路径解析可能会有问题......

编辑这比我预期的更容易......完整路径是通过require.resolve(filename)然后使用fs.statSync。我只是将mtime直接放入缓存对象:

var ext_fn = require.resolve(filename);
var ext_info = fs.statSync(ext_fn);
if (ext_fn in require.cache && require.cache[ext_fn]._x_modtime != ext_info.mtime.getTime()) {
    delete require.cache[ext_fn];
}
var ext = require(filename);
require.cache[ext_fn]._x_modtime = ext_info.mtime.getTime();

1 个答案:

答案 0 :(得分:0)

而不是监控你可以:

如果您知道何时更改文件,则可以向节点发送POSIX信号 并注册一个信号处理程序,以防止您不得不继续检查。 http://nodejs.org/api/process.html#process_signal_events 只选择最合适的一个

process.on('SIGINT', function() {
  watcher.find_modified_files();
});

删除文件

  

/ **
   *模块在需要时缓存在此对象中。    *通过删除此对象的键值,下一个require将重新加载模块    * @type {Object}
   * /

     

require.cache = {};

所以删除条目就足够了,现在你需要做的就是重新加载文件 你可以在任何地方制作一些你需要的文件,并让它导出一个需要函数调用中所需资源的方法

现在用于重新加载和逻辑

创建一些模块,我将其命名为watcher.js

var fs = require('fs');
var path = require('path');

var watchlist = {};

var local_require = function (root, mod) {
    mod = require.resolve(path.join(root, mod));
    fs.stat(mod, function (err, stats) {
        watchlist[mod] = stats.mtime.getTime();
    });
    require(mod);
};

var update = function (path) {
    delete require.cache[path];
    require(path);
};

var find_modified_files = function () {
    Object.keys(watchlist).forEach(function (key) {
        fs.stat(key, function (err, stats) {
            var time = stats.mtime.getTime();
            if (watchlist[key] !== time) {
                watchlist[key] = time;
                update(key);
            }
        });
    });
};

module.exports = {
    require: local_require,
    update: update,
    find_modified_files: find_modified_files
};

使用它:

var watcher = require('./lib/watcher');
var mod_a = watcher.require(__dirname, './mod-a');

您必须提供__dirname,因此要求可以找到相对于您导入的模块的文件,否则将搜索文件相对于观察者模块的位置。

由于require是由nodejs本身提供的glboal,并且被锁定,因此无法更改全局require调用,因此无法跟踪所有需求。

警告

即使这样有效,也可能不是你对它的期望。

如果你持有对所需模块的引用,你需要采用一种特殊的方式与你所观看的模块进行交互,然后,即使在重新加载并从内存中删除之后,你的引用仍将保留以前的版本模块。

作为引用的结果,您将使用的大多数库都无法以这种方式重新加载。

示例:

var watcher = require('./lib/watcher');
var mod_a = watcher.require(__dirname, './mod-a');
var applier = function (ref, scoped) {
  return function (arg) {
    return ref.x(scoped, arg);
  }
}
var closure = closure(mod_a, 'piccle me');
closure('test');

在应用程序返回的函数内部,“ref”变量保存当前的mod_a 它会永远保持它,即使重新加载mod_a,所以相应地改变你的编码风格