banner
Madinah

Madinah

github
twitter
telegram
email
bilibili

NodeJS ローダー

ローダーの読み込み方法#

まず、node --loaderパラメータについて紹介します。このパラメータを使用すると、ESM モジュールの読み込みルールをカスタマイズできます。
node --loader ./my-loader.mjs index.mjsを実行します。index.mjs を読み込む際に、最初に my-loader.mjs の内容が実行されます。my-loader.js を書く場合はどうでしょうか。node には 2 つのフックが組み込まれており、それぞれresolveloadで、インポート時に実行される可能性があります(注:これらのフックは ESM モジュールにのみ有効で、CJS には無効です)。
以下に 2 つのフックの使い方を紹介します。

resolve#

resolve 関数を使用すると、ファイル名とファイルフォーマットの情報を取得できます。渡されたモジュールの情報を変更し、戻り値として返すことができ、その情報は load フックで実行されます。

export async function resolve(specifier, context, nextResolve) {
  const { parentURL = null } = context;
  if (Math.random() > 0.5) {
    return {
      shortCircuit: true,
      url: parentURL ?
        new URL(specifier, parentURL).href :
        new URL(specifier).href,
    };
  }
  if (Math.random() < 0.5) { .
    return nextResolve(specifier, {
      ...context,
      conditions: [...context.conditions, 'another-condition'],
    });
  }
  return nextResolve(specifier);
}

specifier は実行されるファイルのパスで、context は parentURL とインポート可能な conditions のルールを記録します。nextResolve は resolve 関数を記述するものです。ない場合はデフォルトのものになります。返される構造は次の通りです。

{
    format: 'commonjs' | 'module' | 'wasm',
    shortCircuit: boolean, // デフォルトはfalse、resolveフックを終了するかどうか
    url: string; // ファイルのURL、元のURLを処理できます。
}

load#

このフックは、ファイルの URL がどのように取得され、解析されるかを決定します。

export async function load(url, context, defaultLoad) {
  const load = defaultLoad(url, context, defaultLoad)
  const source = load.source

  return {
    format: "module",
    source: `${source} console.log("私はloader.mjsから注入されました")`,
  }
}
console.log("2")

node --loader ./loader.mjs index.mjsを実行すると、2 私はloader.mjsから注入されましたと表示され、実行時に必要なコードを注入できます。

cjs のローダー#

上記ではいくつかの ESM フックについて説明しました。次に、CJS 内で上記の load 機能を実装する方法について説明します。

// モジュールの読み込み
Module.prototype.load = function (filename) {
  var extension = path.extname(filename) || ".js"
  if (!Module._extensions[extension]) extension = ".js"
  Module._extensions[extension](this, filename)
  this.loaded = true
}

// 異なる拡張子の解析メソッドを呼び出す
Module._extensions[".js"] = function (module, filename) {
  var content = fs.readFileSync(filename, "utf8")
  module._compile(stripBOM(content), filename)
}

Module._extensions[".json"] = function (module, filename) {
  var content = fs.readFileSync(filename, "utf8")
  try {
    module.exports = JSON.parse(stripBOM(content))
  } catch (err) {
    err.message = filename + ": " + err.message
    throw err
  }
}

// 最後に_compileメソッドを呼び出してモジュールをコンパイルします。
Module.prototype._compile = function (content, filename) {
  var self = this
  var args = [self.exports, require, self, filename, dirname]
  return compiledWrapper.apply(self.exports, args)
}

このようにして、CJS のローダーも注入できます。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。