在node.js中加载延迟

Sea*_*ter 29 node.js

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

例如,如果我有一个函数需要一个特定的node.js包,而我的代码中其他任何地方都不需要它,我最好require()在该函数内部使用,只有在调用该函数时才包含所需的包.

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

如果是这种情况我应该采取多少措施,我应该尽可能多地尝试编写node.js软件包吗?

Pet*_*ons 39

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

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

在开始处理请求之前,请坚持使用此约定并在应用程序的顶级范围内需要所需的模块.我认为这是一个例子,如果您不得不问是否需要以不寻常的方式编写代码,则不需要以不寻常的方式编写代码.

  • 早期加载对CLI工具没有意义(测试除外,您可以暂时禁用它). (6认同)
  • @PeterLyons您可以向我解释以下行:“节点是单线程的,因此加载模块的内存占用不是按连接的,而是按进程的。加载模块是一次性的操作,可以将其放入内存”。我了解什么是单线程,您是说无论与服务器的连接数量如何,特定模块在整个应用程序中仅加载一次? (3认同)

app*_*e16 8

如果你想延迟加载模块,现在可以使用ES6(Node v6)

编辑:如果您需要访问require的属性(如require.cache),这将不起作用.

module.js

console.log('Module was loaded')
exports.d=3
Run Code Online (Sandbox Code Playgroud)

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');
Run Code Online (Sandbox Code Playgroud)

产量

Before require
After require
Module was loaded
3
After log module
Run Code Online (Sandbox Code Playgroud)

  • 这很微妙,但是 [`Proxy`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) 类看起来很漂亮!不错的发现。 (2认同)