2012-02-03 184 views
13

我想知道在node.js中使用require()是否等效于延迟加载?在node.js中延迟加载

例如,如果我有一个函数,需要一个特定的node.js包,这是我的代码中其他地方不需要的,我最好在该函数内部使用require()以仅在调用该函数时包含所需的包。

由于我对node.js架构缺乏了解,我还不确定这是否会提供任何性能改进?我认为它将使用更少的每个连接到我的服务器的内存。但是,当它必须读取包时,它会增加I/O到磁盘上,还是将它放到内存中?

如果这种情况应该采取这种措施,我是否应该尝试为尽可能多的代码编写node.js包?

回答

21

require()是按需加载。一旦模块被加载,如果再次运行require()调用,它将不会被重新加载。通过将它放入函数而不是顶级模块代码中,可以延迟其加载或可能避免它,如果您从未实际调用该函数。但是,require()是同步的,并且从磁盘加载模块,因此最佳做法是在应用程序启动之前加载所需的任何模块,然后应用程序开始提供请求,然后确保在应用程序运行时只发生异步IO。

节点是单线程的,因此加载模块的内存占用不是每个连接,而是每个进程。加载一个模块是一次性的,可以将它存入内存。

只需坚持这里的约定,并在开始处理请求之前需要在应用程序的顶级范围中需要的模块。我认为这是一个例子,如果你要问你是否需要用一种不寻常的方式编写你的代码,你不需要用不寻常的方式编写你的代码。

+0

感谢彼得,这使得这一切使很多更有意义。 – 2012-02-04 09:29:27

+6

早期加载对于CLI工具没有意义(除了测试,您可以暂时禁用它)。 – sheerun 2014-04-12 15:23:41

+1

@PeterLyons您可以向我解释“Node是单线程的,因此加载模块的内存占用不是每个连接,而是每个进程。加载一个模块是一次性的以便将其存入内存”。我明白单个线程是什么,你的意思是说,无论连接到服务器的数量是多少,一个特定的模块只会在整个应用程序中加载一次? – Deepak 2015-06-06 17:17:00

2

如果你想偷懒加载模块,它现在可以用ES6(节点V6)

编辑:如果你需要的要求(如 require.cache)访问的属性这将无法正常工作。

module.js

console.log('Module was loaded') 
exports.d=3 

main.js

var _require = require; 
var require = function (moduleName) { 
    var module; 
    return new Proxy(function() { 
     if (!module) { 
      module = _require(moduleName) 
     } 
     return module.apply(this, arguments) 
    }, { 
     get: function (target, name) { 
      if (!module) { 
       module = _require(moduleName) 
      } 
      return module[name]; 
     } 
    }) 
}; 

console.log('Before require'); 
var a = require('./module') 
console.log('After require'); 
console.log(a.d) 
console.log('After log module'); 

输出

Before require 
After require 
Module was loaded 
3 
After log module