从内存中的字符串加载node.js模块

ZEC*_*nmo 45 string file require node.js

如果我将文件的内容作为内存中的字符串,而不将其写入磁盘,我将如何要求()文件?这是一个例子:

// Load the file as a string
var strFileContents = fs.readFileSync( "./myUnalteredModule.js", 'utf8' );

// Do some stuff to the files contents
strFileContents[532] = '6';

// Load it as a node module (how would I do this?)
var loadedModule = require( doMagic(strFileContents) );
Run Code Online (Sandbox Code Playgroud)

And*_*rov 55

function requireFromString(src, filename) {
  var Module = module.constructor;
  var m = new Module();
  m._compile(src, filename);
  return m.exports;
}

console.log(requireFromString('module.exports = { test: 1}'));
Run Code Online (Sandbox Code Playgroud)

查看module.js中的_compile,_extensions和_load

  • 实际上你还需要一个让`require`正常工作的东西 - 在filename上调用`Module._nodeModulePaths`(参见https://github.com/floatdrop/require-from-string). (6认同)

Dom*_*nic 41

安德烈已经回答了这个问题,但是我遇到了一个我必须解决的缺点,这可能是其他人感兴趣的.

我希望记忆字符串中的模块能够通过require上面的解决方案加载其他模块,但是模块路径被上述解决方案破坏了(例如没有找到针).我试图找到一个优雅的解决方案来维护路径,通过使用一些现有的功能,但我最终与路径硬连线:

function requireFromString(src, filename) {
  var m = new module.constructor();
  m.paths = module.paths;
  m._compile(src, filename);
  return m.exports;
}

var codeString = 'var needle = require(\'needle\');\n'
  + '[...]\n'
  + 'exports.myFunc = myFunc;';

var virtMod = requireFromString(codeString);
console.log('Available public functions: '+Object.keys(virtMod));
Run Code Online (Sandbox Code Playgroud)

之后,我能够从stringified模块加载所有现有模块.任何评论或更好的解决方案高度赞赏

  • 它适用于单文件模块!太糟糕了,它不适用于多文件模块.我深入研究了它,并且每次调用`require`(例如,当使用`requireFromString`编译的"虚拟模块"需要另一个相对于自身的文件时)将始终最终[检查真实文件](https: //github.com/joyent/node/blob/master/lib/module.js#L134)在文件系统中.除非,我们可以通过`fs.statSync`和`fs.realpathSync`来获取它们来添加虚拟文件路径,多文件模块是遥不可及的.你可能会问为什么:我想通过网络发送模块...... (4认同)

has*_*nge 7

require-from-string做这项工作。

用法:

var requireFromString = require('require-from-string');

requireFromString('module.exports = 1');
//=> 1
Run Code Online (Sandbox Code Playgroud)

  • 我建议扩展您的答案以包含一个示例,说明您将如何使用该模块来解决 OP 的问题。 (2认同)