6

gulp监控工具nodemon,可以监视代码的改动而重启服务器,然而还是觉得若不用重启而直接加载新的代码更方便,所以在网上找了下nodejs热更新的方法,顺便记录一下

其实,方法也是通过监视文件被改动的时候,将缓冲区中已加载的对应模块清除,此时缓冲区中就不保留有该文件模块的代码,直至下一个请求该文件模块到来时,才会去重新加载一遍对应的模块,而正是改动之后的文件模块。

而总结出来要解决的问题有如下三个:

  • 如何更新模块代码

  • 如何使用新模块处理请求

  • 如何释放老模块的资源

先看看node相关的源代码:

// Check the cache for the requested file.
// 1. If a module already exists in the cache: return its exports object.
// 2. If the module is native: call `NativeModule.require()` with the
// filename and return the result.
// 3. Otherwise, create a new module for the file and save it to the cache.
// Then have it load the file contents before returning its exports
// object.
Module._load = function(request, parent, isMain) {
 var filename = Module._resolveFilename(request, parent);
 
 var cachedModule = Module._cache[filename];
 if (cachedModule) {
 return cachedModule.exports;
 }
 
 var module = new Module(filename, parent);
 Module._cache[filename] = module;
 module.load(filename);
 
 return module.exports;
};
 
require.cache = Module._cache;

下面是热更新的测试代码:

app.use('/', function(req, res, next){    //这里的路由要这样写才能使得清除缓存后的下一次请求能重新加载模块
  routes(req, res, next);
});

fs.watch(require.resolve('./routes/index'), function () {
    cleanCache(require.resolve('./routes/index'));    //清除该路径模块的缓存
    try {
        routes = require('./routes/index');
    } catch (ex) {
        console.error('module update failed');
    }
});

function cleanCache(modulePath) {
    var module = require.cache[modulePath];
    // remove reference in module.parent
    if (module.parent) {    
    module.parent.children.splice(module.parent.children.indexOf(module), 1);    //释放老模块的资源
    }
    require.cache[modulePath] = null;    //缓存置空
}

不二冰彬
306 声望6 粉丝