从内存中的string加载node.js模块
如果我将文件的内容作为内存中的string,而不将它写出到磁盘,我将如何要求()一个文件? 这是一个例子:
// 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) );
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}'));
查看module.js中的_compile,_extensions和_load
安德烈已经回答了这个问题,但是我遇到了一个我必须解决的问题,这个问题可能会让其他人感兴趣。
我希望存储的string中的模块能够通过require
来加载其他模块,但是模块path被上面的解决scheme破坏了(所以例如没有find针)。 我试图find一个优雅的解决scheme来维护path,通过使用一些现有的function,但我最终以硬布线的path:
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));
之后,我可以加载string化模块中的所有现有模块。 任何意见或更好的解决scheme高度赞赏
require-from-string
包完成这项工作。
用法:
var requireFromString = require('require-from-string'); requireFromString('module.exports = 1'); //=> 1
基于Andrey Sidorov&Dominic的解决scheme,我不能要求一个string化的模块,然后我build议这个版本的事实令我感到难过。
码:
void function() { 'use strict'; const EXTENSIONS = ['.js', '.json', '.node']; var Module, path, cache, resolveFilename, demethodize, hasOwnProperty, dirname, parse, resolve, stringify, virtual; Module = require('module'); path = require('path'); cache = Module._cache; resolveFilename = Module._resolveFilename; dirname = path.dirname; parse = path.parse; resolve = path.resolve; demethodize = Function.bind.bind(Function.call); hasOwnProperty = demethodize(Object.prototype.hasOwnProperty); Module._resolveFilename = function(request, parent) { var filename; // Pre-resolution filename = resolve(parse(parent.filename).dir, request); // Adding extension, if needed if (EXTENSIONS.indexOf(parse(filename).ext) === -1) { filename += '.js'; } // If the module exists or is virtual, return the filename if (virtual || hasOwnProperty(cache, filename)) { return filename; } // Preserving the native behavior return resolveFilename.apply(Module, arguments); }; Module._register = function(request, parent, src) { var filename, module; // Enabling virtual resolution virtual = true; filename = Module._resolveFilename(request, parent); // Disabling virtual resolution virtual = false; // Conflicts management if (hasOwnProperty(cache, filename)) { error = new Error('Existing module "' + request + '"'); error.code = 'MODULE_EXISTS'; throw error; } // Module loading cache[filename] = module = new Module(filename, parent); module.filename = filename; module.paths = Module._nodeModulePaths(dirname(filename)); module._compile(stringify(src), filename); module.loaded = true; return module; }; stringify = function(src) { // If src is a function, turning to IIFE src return typeof src === 'function' ? 'void ' + src.toString() + '();' : src; }; }(); void function() { var Module, parentModule, child; Module = require('module'); // Creating a parent module from string parentModule = Module._register('parent', process.mainModule, ` module.exports = { name: module.filename, getChild: function() { return require('child'); } }; `); // Creating a child module from function Module._register('child', parentModule, function() { module.exports = { name: module.filename, getParent: function() { return module.parent.exports; } }; }); child = require('child'); console.log(child === child.getParent().getChild()); }();
用法:
void function() { var Module, parentModule, child; Module = require('module'); // Creating a parent module from string parentModule = Module._register('parent', process.mainModule, ` module.exports = { name: module.filename, getChild: function() { return require('child'); } }; `); // Creating a child module from function Module._register('child', parentModule, function() { module.exports = { name: module.filename, getParent: function() { return module.parent.exports; } }; }); child = require('child'); console.log(child === child.getParent().getChild()); }();
*你可以看到,它包含一个函数formater,它提供了一种从函数创build一些模块的方法。
我认为更好的方法来处理这个问题将是一个参数,你可以在之后设置…
如文件内部:myUnalteredModule.js
exports.setChanges = function( args )...
那么你可以这样做:
var loadedModule = require( 'myUnalteredModule' ); loadedModule