1. 程式人生 > >nodejs 熱更新

nodejs 熱更新

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;    //快取置空
}