2013-07-10 5 views
31

ファイルの内容をディスクに書き込まずにメモリ内の文字列として使用する場合、ファイルをどのように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)); 
+0

私はあなたのために完全な答えを持っていませんが、Node.jsのモジュールのコードを実行する方法をチェックアウトすることができます。 https://github.com/joyent/node/blob/7373c4ddb7143fb7da75feda39c70788fb1bcfc7/src/node.js#L768またL813を見てください – travis

答えて

39
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}')); 

_compile、_extensions、_loadを参照してくださいmodule.js

+3

実際に 'require'を正しく動作させるためにもう1つ必要です - ファイル名に' Module._nodeModulePaths'を呼び出してください(https://github.com/floatdrop/require-from-stringを参照)。 – floatdrop

-3

...

なファイル内など

:myUnalteredModule.js

exports.setChanges = function(args)... 
ここでは一例です

は、次に、あなたが行うことができます:

var loadedModule = require('myUnalteredModule'); 
loadedModule 
+0

私はそのオプションを持っていません。私は文字列としてモジュールの内容を変更できる必要があり、私は本当に一時ファイルを作成しないようにしたいと思います。 – ZECTBynmo

33

質問はすでにAndreyによって回答されていますが、私は解決しなければならなかった、他の人にとっては興味深い欠点に遭遇しました。

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)); 

その後、私は文字列化されたモジュールからすべての既存のモジュールをロードすることができました。 コメントやより良い解決策が高く評価されています!

+0

共有してくれてありがとう、これは私に多くの時間のデバッグを保存しました! – Deleteman

+3

これは、単一ファイルモジュールに最適です!多すぎると、マルチファイルモジュールではうまくいかないでしょう。私はそれを掘り下げ、「要求する」(例えば、'requireFromString'でコンパイルされた"仮想モジュール "がそれ自身に関連した別のファイルを必要とする場合、常に実際のファイルをチェックすることになります(https://github.com/joyent/node/blob/master/lib/module .js#L134)をファイルシステムに追加します。ただし、 'fs.statSync'と' fs.realpathSync'がそれらを拾うような方法で仮想ファイルパスを追加できない限り、マルチファイルモジュールは手の届かないところにあります。理由:私はネットワーク経由でモジュールを送信したいと思うかもしれません... – Domi

+0

require.cacheのエントリがありません – xamiro

2

Andrey Sidorov &ドミニクのソリューションに基づいて、ストリンジェライズされたモジュールを必要としないという事実に悲しかったので、このバージョンをお勧めします。

コード:

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()); 
}(); 

*あなたが見ることができるように、それは関数からいくつかのモジュールを作成する方法を提供し、機能フォーマッタが含まれています。

+0

これにいくつかのコメントを追加できますか? –

+1

ちょうど完了...;) –

2

require-from-string packageはジョブを実行します。

使用法:

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

requireFromString('module.exports = 1'); 
//=> 1 
+1

OPの問題を解決するためにそのモジュールを使用する方法の例を含めるように答えを拡大することをお勧めします。 – brandonscript

関連する問題