前提・実現したいこと
WSH/JScriptでも、Node.jsにおけるrequire()のように細かく機能別にモジュールとして分割管理をしたいと考えております。
最終的には、本家のrequire()と同等に動作する関数を用意することで、作成したモジュールをNode.jsでも共用利用できることを目指しています。
元々は、WSFを採用することで、モジュール単位で複数に分割したファイルを<script>タグで呼び出すという形で上記の目的の一部は達成できていました。
しかし、Node.jsとの共用利用という意味では各モジュールをUMD化する必要性もあるし、何よりモジュールから別のモジュールを呼び出すということができません。
そのため、ADODB.Streamを利用してファイルを読み込んでeval()することにより、疑似的に動作する関数を定義してみたのですが、モジュールから別のモジュールを呼び出す際のパス指定において問題が生じたので質問させていただきます。
発生している問題
読み込み対象が絶対パス、もしくはWSFファイルを起点とした相対パスで指定された場合には、希望通り動作します。
一方で、モジュールから別のモジュールを呼び出すといった場合に、本家のrequire()の場合は「呼び出し元を起点とした相対パス」で呼び出し先を指定できますが、現状ではWSFファイルを起点とした相対パスでしか指定できないといった問題が生じており、モジュールの再利用性が損なわれています。
該当のソースコード
ファイル構成
current L module | L echo | | L echo.js | | | L test.js | L require-test.js L require-test.wsf
require-test.wsf
wsf
1<?xml version="1.0" encoding="utf-8" standalone="yes" ?> 2<package> 3<job> 4 <script language="JScript" src="require-test.js"></script> 5 <script language="JScript"><![CDATA[ 6 var test = require('module/test.js'); 7 test(); 8 9 var echoFromCache = require('module/echo/echo.js'); 10 echoFromCache('echo by cached module'); // キャッシュの再利用性の確認 11 ]]></script> 12</job> 13</package>
require-test.js
js
1var require = function(modulePath) { 2 var moduleName = modulePath.replace(/^(?:.*?[/\])?([^/\]+?)(?:.js)?$/, '$1'); // キャッシュのためのモジュール名 3 4 // 1.キャッシュから呼び出し 5 if (require.cache.hasOwnProperty(moduleName)) { 6 WScript.Echo('"' + moduleName + '" is cached'); 7 return require.cache[moduleName]; 8 } 9 10 // 2.ファイルから読み込み 11 var readFile = function(filePath) { 12 var st = new ActiveXObject('ADODB.Stream'); 13 st.mode = 3; // 読み取り/書き込み両方モード 14 st.type = 2; // テキストデータ 15 st.charset = 'UTF-8'; 16 st.Open(); 17 try { 18 st.LoadFromFile(filePath); 19 var textData = st.ReadText(); 20 } catch(e) { 21 throw new Error(e.message + '\n' + 'filePath = ' + filePath); 22 } 23 st.Close(); 24 return textData; 25 }; 26 27 // TODO: Node require のパス探査機構の構築 28 // 1.上位ディレクトリをたどって、node_modules/{MODULE} を探す。 29 // 2.拡張子省略時に、{MODULE}.js -> {MODULE}.json -> {MODULE}/index.js -> {MODULE}/index.json も探す。 30 var loadedString = readFile(modulePath); 31 32 var evalCode = ( 33 '(function() {' + 34 /**/'var _module = {}, _exports = _module.exports = {};' + 35 /**/'(function(require, module, exports) {' + 36 /******/loadedString + 37 /**/'})(require, _module, _exports);' + 38 /**/'return _module.exports;' + 39 '})();' 40 ); 41 var evalModule = eval(evalCode); // module.exports 42 43 WScript.Echo('"' + moduleName + '" load from file'); 44 return require.cache[moduleName] = evalModule; // キャッシュ 45}; 46 47require.cache = {}; // モジュールのキャッシュ先
module/test.js
js
1var echo = require('module/echo/echo.js'); // wsfファイルのあるディレクトリ基準となってしまう 2// var echo = require('echo/echo.js'); // test.jsからみた相対パス指定したい 3var test = function() { 4 echo('echo by test-function'); 5}; 6module.exports = test;
module/echo/echo.js
js
1module.exports = function echo(text) { 2 WScript.Echo(text); 3};
試したこと
WScript.ScriptFullName で取得できるのはWSFファイルのパスであり、各スクリプトファイルのパスを取得する方法がわかりません。
上の例でいうと、test.jsのパスがわかれば、echo.jsへの相対パスを絶対パスに変換したり、カレントを変更してしまうといったことで対応できます。
Node.jsでいうところの __dirname が分かれば早いのですが・・・。
回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/07/06 07:27