Modules: node:module
API
追加: v0.3.7
Module
オブジェクト
Module
のインスタンス、module
変数でしばしば見られる CommonJS モジュールとやり取りする際の一般的なユーティリティメソッドを提供します。import 'node:module'
または require('node:module')
でアクセスします。
module.builtinModules
[履歴]
バージョン | 変更点 |
---|---|
v23.5.0 | リストにプレフィックスのみのモジュールも含まれるようになりました。 |
v9.3.0, v8.10.0, v6.13.0 | 追加: v9.3.0, v8.10.0, v6.13.0 |
Node.js によって提供されるすべてのモジュールの名前のリスト。モジュールがサードパーティによって管理されているかどうかを確認するために使用できます。
このコンテキストでの module
は、モジュールラッパー によって提供されるオブジェクトと同じではありません。アクセスするには、Module
モジュールを require します。
// module.mjs
// ECMAScript モジュール内
import { builtinModules as builtin } from 'node:module'
// module.cjs
// CommonJS モジュール内
const builtin = require('node:module').builtinModules
module.createRequire(filename)
追加: v12.2.0
filename
<string> | <URL> require 関数を構築するために使用されるファイル名。ファイル URL オブジェクト、ファイル URL 文字列、または絶対パス文字列である必要があります。- 返却値: <require> Require 関数
import { createRequire } from 'node:module'
const require = createRequire(import.meta.url)
// sibling-module.js は CommonJS モジュールです。
const siblingModule = require('./sibling-module')
module.findPackageJSON(specifier[, base])
追加: v23.2.0
specifier
<string> | <URL> 取得するpackage.json
のモジュール指定子。ベア指定子 を渡すと、パッケージのルートにあるpackage.json
が返されます。相対指定子 または 絶対指定子 を渡すと、最も近い親のpackage.json
が返されます。base
<string> | <URL> 包含モジュールの絶対位置 (file:
URL 文字列または FS パス)。CJS の場合は__filename
(__dirname
ではない!)を使用します。ESM の場合はimport.meta.url
を使用します。specifier
が 絶対指定子 の場合は渡す必要はありません。- 返却値: <string> | <undefined>
package.json
が見つかった場合はパス。startLocation
がパッケージの場合、パッケージのルートpackage.json
です。相対または未解決の場合、startLocation
に最も近いpackage.json
です。
/path/to/project
├ packages/
├ bar/
├ bar.js
└ package.json // name = '@foo/bar'
└ qux/
├ node_modules/
└ some-package/
└ package.json // name = 'some-package'
├ qux.js
└ package.json // name = '@foo/qux'
├ main.js
└ package.json // name = '@foo'
// /path/to/project/packages/bar/bar.js
import { findPackageJSON } from 'node:module'
findPackageJSON('..', import.meta.url)
// '/path/to/project/package.json'
// 代わりに絶対指定子を渡した場合も同じ結果になります。
findPackageJSON(new URL('../', import.meta.url))
findPackageJSON(import.meta.resolve('../'))
findPackageJSON('some-package', import.meta.url)
// '/path/to/project/packages/bar/node_modules/some-package/package.json'
// 絶対指定子を渡すと、解決されたモジュールがネストされた `package.json` を持つサブフォルダー内にある場合、異なる結果が得られる可能性があります。
findPackageJSON(import.meta.resolve('some-package'))
// '/path/to/project/packages/bar/node_modules/some-package/some-subfolder/package.json'
findPackageJSON('@foo/qux', import.meta.url)
// '/path/to/project/packages/qux/package.json'
// /path/to/project/packages/bar/bar.js
const { findPackageJSON } = require('node:module')
const { pathToFileURL } = require('node:url')
const path = require('node:path')
findPackageJSON('..', __filename)
// '/path/to/project/package.json'
// 代わりに絶対指定子を渡した場合も同じ結果になります。
findPackageJSON(pathToFileURL(path.join(__dirname, '..')))
findPackageJSON('some-package', __filename)
// '/path/to/project/packages/bar/node_modules/some-package/package.json'
// 絶対指定子を渡すと、解決されたモジュールがネストされた `package.json` を持つサブフォルダー内にある場合、異なる結果が得られる可能性があります。
findPackageJSON(pathToFileURL(require.resolve('some-package')))
// '/path/to/project/packages/bar/node_modules/some-package/some-subfolder/package.json'
findPackageJSON('@foo/qux', __filename)
// '/path/to/project/packages/qux/package.json'
module.isBuiltin(moduleName)
追加: v18.6.0, v16.17.0
import { isBuiltin } from 'node:module'
isBuiltin('node:fs') // true
isBuiltin('fs') // true
isBuiltin('wss') // false
module.register(specifier[, parentURL][, options])
[履歴]
バージョン | 変更点 |
---|---|
v20.8.0, v18.19.0 | WHATWG URL インスタンスのサポートを追加。 |
v20.6.0, v18.19.0 | 追加: v20.6.0, v18.19.0 |
specifier
<string> | <URL> 登録されるカスタマイズフック。これはimport()
に渡されるものと同じ文字列である必要があります。ただし、相対パスの場合、parentURL
を基準に解決されます。parentURL
<string> | <URL>import.meta.url
のようなベース URL を基準にspecifier
を解決したい場合は、ここにその URL を渡すことができます。デフォルト:'data:'
options
<Object>parentURL
<string> | <URL>import.meta.url
のようなベース URL を基準にspecifier
を解決したい場合は、ここにその URL を渡すことができます。このプロパティは、parentURL
が 2 番目の引数として指定されている場合は無視されます。デフォルト:'data:'
data
<any>initialize
フックに渡す任意のクローン可能な JavaScript 値。transferList
<Object[]>initialize
フックに渡される転送可能オブジェクト。
Node.js モジュールの解決とロード動作をカスタマイズするフックをエクスポートするモジュールを登録します。カスタマイズフック を参照してください。
module.registerHooks(options)
追加: v23.5.0
options
<Object>load
<Function> | <undefined> load hook を参照してください。 デフォルト:undefined
。resolve
<Function> | <undefined> resolve hook を参照してください。 デフォルト:undefined
。
Node.js モジュールの解決と読み込みの動作をカスタマイズする hooks を登録します。カスタマイズフック を参照してください。
module.stripTypeScriptTypes(code[, options])
追加: v23.2.0
code
<string> 型注釈を削除するコード。options
<Object>戻り値: <string> 型注釈が削除されたコード。
module.stripTypeScriptTypes()
は、TypeScript コードから型注釈を削除します。vm.runInContext()
またはvm.compileFunction()
で実行する前に、TypeScript コードから型注釈を削除するために使用できます。デフォルトでは、コードにEnums
などの変換を必要とする TypeScript 機能が含まれている場合、エラーがスローされます。詳細については、type-stripping を参照してください。mode が'transform'
の場合、TypeScript の機能も JavaScript に変換されます。詳細については、TypeScript 機能の変換 を参照してください。mode が'strip'
の場合、位置が保持されるため、ソースマップは生成されません。sourceMap
が提供されている場合、mode が'strip'
の場合、エラーがスローされます。
警告: この関数の出力は、TypeScript パーサーの変更により、Node.js のバージョン間で安定しているとはみなさないでください。
import { stripTypeScriptTypes } from 'node:module'
const code = 'const a: number = 1;'
const strippedCode = stripTypeScriptTypes(code)
console.log(strippedCode)
// 出力: const a = 1;
const { stripTypeScriptTypes } = require('node:module')
const code = 'const a: number = 1;'
const strippedCode = stripTypeScriptTypes(code)
console.log(strippedCode)
// 出力: const a = 1;
sourceUrl
が提供されている場合、出力の末尾にコメントとして追加されます。
import { stripTypeScriptTypes } from 'node:module'
const code = 'const a: number = 1;'
const strippedCode = stripTypeScriptTypes(code, { mode: 'strip', sourceUrl: 'source.ts' })
console.log(strippedCode)
// 出力: const a = 1\n\n//# sourceURL=source.ts;
const { stripTypeScriptTypes } = require('node:module')
const code = 'const a: number = 1;'
const strippedCode = stripTypeScriptTypes(code, { mode: 'strip', sourceUrl: 'source.ts' })
console.log(strippedCode)
// 出力: const a = 1\n\n//# sourceURL=source.ts;
mode
が 'transform'
の場合、コードは JavaScript に変換されます。
import { stripTypeScriptTypes } from 'node:module'
const code = `
namespace MathUtil {
export const add = (a: number, b: number) => a + b;
}`
const strippedCode = stripTypeScriptTypes(code, { mode: 'transform', sourceMap: true })
console.log(strippedCode)
// 出力:
// var MathUtil;
// (function(MathUtil) {
// MathUtil.add = (a, b)=>a + b;
// })(MathUtil || (MathUtil = {}));
// # sourceMappingURL=data:application/json;base64, ...
const { stripTypeScriptTypes } = require('node:module')
const code = `
namespace MathUtil {
export const add = (a: number, b: number) => a + b;
}`
const strippedCode = stripTypeScriptTypes(code, { mode: 'transform', sourceMap: true })
console.log(strippedCode)
// 出力:
// var MathUtil;
// (function(MathUtil) {
// MathUtil.add = (a, b)=>a + b;
// })(MathUtil || (MathUtil = {}));
// # sourceMappingURL=data:application/json;base64, ...
module.syncBuiltinESMExports()
追加: v12.12.0
module.syncBuiltinESMExports()
メソッドは、組み込みの ES Modules のすべてのライブバインディングを更新して、CommonJS エクスポートのプロパティと一致させます。これは、ES Modules からエクスポートされた名前を追加または削除しません。
const fs = require('node:fs')
const assert = require('node:assert')
const { syncBuiltinESMExports } = require('node:module')
fs.readFile = newAPI
delete fs.readFileSync
function newAPI() {
// ...
}
fs.newAPI = newAPI
syncBuiltinESMExports()
import('node:fs').then(esmFS => {
// 既存の readFile プロパティを新しい値と同期します
assert.strictEqual(esmFS.readFile, newAPI)
// readFileSync は必須の fs から削除されました
assert.strictEqual('readFileSync' in fs, false)
// syncBuiltinESMExports() は esmFS から readFileSync を削除しません
assert.strictEqual('readFileSync' in esmFS, true)
// syncBuiltinESMExports() は名前を追加しません
assert.strictEqual(esmFS.newAPI, undefined)
})
モジュールコンパイルキャッシュ
[履歴]
バージョン | 変更 |
---|---|
v22.8.0 | ランタイムアクセス用の初期 JavaScript API を追加。 |
v22.1.0 | 追加: v22.1.0 |
モジュールコンパイルキャッシュは、module.enableCompileCache()
メソッドまたは NODE_COMPILE_CACHE=dir
環境変数を使用して有効にできます。有効にすると、Node.js が CommonJS または ECMAScript モジュールをコンパイルするたびに、指定されたディレクトリに永続化されたディスク上の V8 コードキャッシュ を使用してコンパイルを高速化します。これにより、モジュールグラフの最初のロードが遅くなる可能性がありますが、モジュールの内容が変更されない場合、同じモジュールグラフの後続のロードは大幅に高速化される可能性があります。
ディスク上の生成されたコンパイルキャッシュをクリーンアップするには、キャッシュディレクトリを削除するだけです。キャッシュディレクトリは、同じディレクトリがコンパイルキャッシュストレージに使用される次のときに再作成されます。ディスクが古いキャッシュでいっぱいになるのを防ぐために、os.tmpdir()
の下のディレクトリを使用することをお勧めします。ディレクトリを指定せずに module.enableCompileCache()
の呼び出しによってコンパイルキャッシュが有効になっている場合、Node.js は、NODE_COMPILE_CACHE=dir
環境変数が設定されている場合はそれを使用し、それ以外の場合はデフォルトで path.join(os.tmpdir(), 'node-compile-cache')
を使用します。実行中の Node.js インスタンスで使用されるコンパイルキャッシュディレクトリを見つけるには、module.getCompileCacheDir()
を使用します。
現在、コンパイルキャッシュを V8 JavaScript コードカバレッジ と共に使用すると、コードキャッシュからデシリアライズされた関数では、V8 が収集するカバレッジの精度が低下する可能性があります。正確なカバレッジを生成するためにテストを実行する場合は、これをオフにすることをお勧めします。
有効なモジュールコンパイルキャッシュは、NODE_DISABLE_COMPILE_CACHE=1
環境変数によって無効にできます。これは、コンパイルキャッシュが予期しない動作や望ましくない動作 (例: テストカバレッジの精度が低い) を引き起こす場合に役立ちます。
あるバージョンの Node.js で生成されたコンパイルキャッシュは、別のバージョンの Node.js では再利用できません。異なるバージョンの Node.js で生成されたキャッシュは、キャッシュを永続化するために同じベースディレクトリが使用されている場合は個別に保存されるため、共存できます。
現時点では、コンパイルキャッシュが有効になっていて、モジュールが新たにロードされると、コードキャッシュはコンパイルされたコードからすぐに生成されますが、Node.js インスタンスが終了しようとしているときにのみディスクに書き込まれます。これは変更される可能性があります。module.flushCompileCache()
メソッドを使用すると、アプリケーションが他の Node.js インスタンスを生成し、親が終了するずっと前にそれらにキャッシュを共有させたい場合に、累積されたコードキャッシュがディスクにフラッシュされるようにすることができます。
module.constants.compileCacheStatus
追加: v22.8.0
以下の定数は、モジュールコンパイルキャッシュを有効にする試みの結果を示すために、module.enableCompileCache()
によって返されるオブジェクトの status
フィールドとして返されます。
定数 | 説明 |
---|---|
ENABLED | Node.js はコンパイルキャッシュを正常に有効にしました。コンパイルキャッシュの保存に使用されるディレクトリは、返されるオブジェクトの directory フィールドに返されます。 |
ALREADY_ENABLED | コンパイルキャッシュは、以前の module.enableCompileCache() の呼び出し、または NODE_COMPILE_CACHE=dir 環境変数のいずれかによって、すでに有効にされています。コンパイルキャッシュの保存に使用されるディレクトリは、返されるオブジェクトの directory フィールドに返されます。 |
FAILED | Node.js はコンパイルキャッシュを有効にできません。これは、指定されたディレクトリを使用する権限がない、またはさまざまな種類のファイルシステムエラーが原因である可能性があります。失敗の詳細は、返されるオブジェクトの message フィールドに返されます。 |
DISABLED | 環境変数 NODE_DISABLE_COMPILE_CACHE=1 が設定されているため、Node.js はコンパイルキャッシュを有効にできません。 |
module.enableCompileCache([cacheDir])
追加: v22.8.0
cacheDir
<string> | <undefined> コンパイルキャッシュが保存/取得されるディレクトリを指定するためのオプションのパス。- 返り値: <Object>
status
<integer>module.constants.compileCacheStatus
のいずれか。message
<string> | <undefined> Node.js がコンパイルキャッシュを有効にできない場合、これにはエラーメッセージが含まれます。status
がmodule.constants.compileCacheStatus.FAILED
の場合にのみ設定されます。directory
<string> | <undefined> コンパイルキャッシュが有効になっている場合、これにはコンパイルキャッシュが保存されているディレクトリが含まれます。status
がmodule.constants.compileCacheStatus.ENABLED
またはmodule.constants.compileCacheStatus.ALREADY_ENABLED
の場合にのみ設定されます。
現在の Node.js インスタンスでモジュールコンパイルキャッシュを有効にします。
cacheDir
が指定されていない場合、Node.js は、NODE_COMPILE_CACHE=dir
環境変数が設定されている場合はその環境変数で指定されたディレクトリを使用し、それ以外の場合は path.join(os.tmpdir(), 'node-compile-cache')
を使用します。一般的なユースケースでは、cacheDir
を指定せずに module.enableCompileCache()
を呼び出すことをお勧めします。これにより、必要に応じて NODE_COMPILE_CACHE
環境変数でディレクトリを上書きできます。
コンパイルキャッシュはアプリケーションの機能に必須ではない静かな最適化であるため、このメソッドはコンパイルキャッシュを有効にできない場合に例外をスローしないように設計されています。代わりに、デバッグを支援するために message
フィールドにエラーメッセージを含むオブジェクトを返します。コンパイルキャッシュが正常に有効になっている場合、返されたオブジェクトの directory
フィールドには、コンパイルキャッシュが保存されているディレクトリへのパスが含まれます。返されたオブジェクトの status
フィールドは、モジュールコンパイルキャッシュを有効にする試みの結果を示す module.constants.compileCacheStatus
値のいずれかになります。
このメソッドは、現在の Node.js インスタンスのみに影響します。子ワーカースレッドで有効にするには、子ワーカースレッドでもこのメソッドを呼び出すか、process.env.NODE_COMPILE_CACHE
の値をコンパイルキャッシュディレクトリに設定して、動作を子ワーカーに継承できるようにします。ディレクトリは、このメソッドによって返される directory
フィールド、または module.getCompileCacheDir()
で取得できます。
module.flushCompileCache()
追加: v23.0.0
現在の Node.js インスタンスで既にロードされたモジュールから蓄積されたモジュールコンパイルキャッシュをディスクにフラッシュします。これは、フラッシュするファイルシステム操作が成功するかどうかに関わらず、すべて終了した後に返ります。エラーが発生した場合、コンパイルキャッシュのミスはアプリケーションの実際の操作を妨げるべきではないため、これはサイレントに失敗します。
module.getCompileCacheDir()
追加: v22.8.0
- 戻り値: <string> | <undefined> モジュールコンパイルキャッシュディレクトリへのパス(有効な場合)、またはそうでない場合は
undefined
。
カスタマイズフック
[履歴]
バージョン | 変更点 |
---|---|
v23.5.0 | 同期およびスレッド内フックのサポートを追加。 |
v20.6.0, v18.19.0 | globalPreload を置き換える initialize フックを追加。 |
v18.6.0, v16.17.0 | ローダーのチェーンのサポートを追加。 |
v16.12.0 | getFormat 、getSource 、transformSource 、および globalPreload を削除。load フックおよび getGlobalPreload フックを追加。 |
v8.8.0 | 追加: v8.8.0 |
現在サポートされているモジュールカスタマイズフックには、次の 2 種類があります。
有効化
モジュールの解決とロードは、次のようにカスタマイズできます。
フックは、--import
または --require
フラグを使用して、アプリケーションコードが実行される前に登録できます。
node --import ./register-hooks.js ./my-app.js
node --require ./register-hooks.js ./my-app.js
// register-hooks.js
// このファイルはトップレベルのawaitを含まない場合にのみrequire()できます。
// 専用のスレッドで非同期フックを登録するには、module.register()を使用します。
import { register } from 'node:module'
register('./hooks.mjs', import.meta.url)
// register-hooks.js
const { register } = require('node:module')
const { pathToFileURL } = require('node:url')
// 専用のスレッドで非同期フックを登録するには、module.register()を使用します。
register('./hooks.mjs', pathToFileURL(__filename))
// メインスレッドで同期フックを登録するには、module.registerHooks()を使用します。
import { registerHooks } from 'node:module'
registerHooks({
resolve(specifier, context, nextResolve) {
/* 実装 */
},
load(url, context, nextLoad) {
/* 実装 */
},
})
// メインスレッドで同期フックを登録するには、module.registerHooks()を使用します。
const { registerHooks } = require('node:module')
registerHooks({
resolve(specifier, context, nextResolve) {
/* 実装 */
},
load(url, context, nextLoad) {
/* 実装 */
},
})
--import
または --require
に渡されるファイルは、依存関係からのエクスポートでもかまいません。
node --import some-package/register ./my-app.js
node --require some-package/register ./my-app.js
ここで、some-package
には、次の register-hooks.js
の例のように、register()
を呼び出すファイルにマッピングする /register
エクスポートを定義する "exports"
フィールドがあります。
--import
または --require
を使用すると、アプリケーションのエントリーポイントや、デフォルトでワーカー スレッドなど、アプリケーションファイルがインポートされる前にフックが登録されることが保証されます。
または、エントリーポイントから register()
および registerHooks()
を呼び出すこともできます。ただし、フックが登録された後に実行される必要のある ESM コードには、動的な import()
を使用する必要があります。
import { register } from 'node:module'
register('http-to-https', import.meta.url)
// これは動的な `import()` であるため、`http-to-https` フックは
// `./my-app.js` およびインポートまたはrequireする他のすべてのファイルを処理するために実行されます。
await import('./my-app.js')
const { register } = require('node:module')
const { pathToFileURL } = require('node:url')
register('http-to-https', pathToFileURL(__filename))
// これは動的な `import()` であるため、`http-to-https` フックは
// `./my-app.js` およびインポートまたはrequireする他のすべてのファイルを処理するために実行されます。
import('./my-app.js')
カスタマイズフックは、登録よりも後にロードされたモジュールと、import
と組み込みの require
を介して参照するモジュールに対して実行されます。module.createRequire()
を使用してユーザーが作成した require
関数は、同期フックによってのみカスタマイズできます。
この例では、http-to-https
フックを登録していますが、これらは後でインポートされるモジュールでのみ利用可能になります。この場合、my-app.js
と、CommonJS 依存関係で import
または組み込みの require
を介して参照するすべてです。
import('./my-app.js')
が静的な import './my-app.js'
であった場合、アプリは http-to-https
フックが登録される前に 既にロードされていたことになります。これは、ES モジュール仕様によるものであり、静的なインポートは最初にツリーの葉から評価され、次に幹に戻って評価されます。 my-app.js
内に静的なインポートを含めることができ、これらは my-app.js
が動的にインポートされるまで評価されません。
同期フックを使用する場合、import
、require
、および createRequire()
を使用して作成されたユーザー require
の両方がサポートされます。
import { registerHooks, createRequire } from 'node:module'
registerHooks({
/* 同期フックの実装 */
})
const require = createRequire(import.meta.url)
// 同期フックは、import、require()、および createRequire() を介して作成されたユーザーrequire()関数に影響します。
await import('./my-app.js')
require('./my-app-2.js')
const { register, registerHooks } = require('node:module')
const { pathToFileURL } = require('node:url')
registerHooks({
/* 同期フックの実装 */
})
const userRequire = createRequire(__filename)
// 同期フックは、import、require()、および createRequire() を介して作成されたユーザーrequire()関数に影響します。
import('./my-app.js')
require('./my-app-2.js')
userRequire('./my-app-3.js')
最後に、アプリが実行される前にフックを登録したいだけで、その目的のために別のファイルを作成したくない場合は、data:
URL を --import
に渡すことができます。
node --import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; register("http-to-https", pathToFileURL("./"));' ./my-app.js
チェイニング
register
は複数回呼び出すことができます。
// entrypoint.mjs
import { register } from 'node:module'
register('./foo.mjs', import.meta.url)
register('./bar.mjs', import.meta.url)
await import('./my-app.mjs')
// entrypoint.cjs
const { register } = require('node:module')
const { pathToFileURL } = require('node:url')
const parentURL = pathToFileURL(__filename)
register('./foo.mjs', parentURL)
register('./bar.mjs', parentURL)
import('./my-app.mjs')
この例では、登録されたフックはチェーンを形成します。これらのチェーンは後入れ先出し (LIFO) で実行されます。もし foo.mjs
と bar.mjs
の両方が resolve
フックを定義している場合、それらは次のように呼び出されます (右から左に注意してください): node のデフォルト ← ./foo.mjs
← ./bar.mjs
(最初に ./bar.mjs
、次に ./foo.mjs
、そして Node.js のデフォルト)。他のすべてのフックについても同様です。
登録されたフックは、register
自体にも影響を与えます。この例では、bar.mjs
は foo.mjs
によって登録されたフックを介して解決およびロードされます (なぜなら、foo
のフックはすでにチェーンに追加されているからです)。これにより、以前に登録されたフックが JavaScript にトランスパイルされる限り、非 JavaScript 言語でフックを記述するようなことが可能になります。
register
メソッドは、フックを定義するモジュール内からは呼び出すことができません。
registerHooks
のチェイニングも同様に機能します。同期フックと非同期フックが混在している場合、常に同期フックが最初に実行され、その後に非同期フックが実行されます。つまり、最後に実行される同期フックでは、その次のフックには非同期フックの呼び出しが含まれます。
// entrypoint.mjs
import { registerHooks } from 'node:module'
const hook1 = {
/* フックの実装 */
}
const hook2 = {
/* フックの実装 */
}
// hook2 は hook1 の前に実行されます。
registerHooks(hook1)
registerHooks(hook2)
// entrypoint.cjs
const { registerHooks } = require('node:module')
const hook1 = {
/* フックの実装 */
}
const hook2 = {
/* フックの実装 */
}
// hook2 は hook1 の前に実行されます。
registerHooks(hook1)
registerHooks(hook2)
モジュールカスタマイズフックとの通信
非同期フックは、アプリケーションコードを実行するメインスレッドとは別の専用スレッドで実行されます。これは、グローバル変数を変更しても他のスレッドに影響を与えず、スレッド間で通信するにはメッセージチャネルを使用する必要があることを意味します。
register
メソッドを使用して、initialize
フックにデータを渡すことができます。フックに渡されるデータには、ポートのような転送可能なオブジェクトを含めることができます。
import { register } from 'node:module'
import { MessageChannel } from 'node:worker_threads'
// この例は、メッセージチャネルを使用して、`port2` をフックに送信することで
// フックと通信する方法を示しています。
const { port1, port2 } = new MessageChannel()
port1.on('message', msg => {
console.log(msg)
})
port1.unref()
register('./my-hooks.mjs', {
parentURL: import.meta.url,
data: { number: 1, port: port2 },
transferList: [port2],
})
const { register } = require('node:module')
const { pathToFileURL } = require('node:url')
const { MessageChannel } = require('node:worker_threads')
// この例は、メッセージチャネルを使用して、`port2` をフックに送信することで
// フックと通信する方法を示しています。
const { port1, port2 } = new MessageChannel()
port1.on('message', msg => {
console.log(msg)
})
port1.unref()
register('./my-hooks.mjs', {
parentURL: pathToFileURL(__filename),
data: { number: 1, port: port2 },
transferList: [port2],
})
同期モジュールフックは、アプリケーションコードが実行される同じスレッドで実行されます。それらは、メインスレッドがアクセスするコンテキストのグローバル変数を直接変更できます。
フック
module.register()
によって受け入れられる非同期フック
register
メソッドを使用して、一連のフックをエクスポートするモジュールを登録できます。フックは、モジュールの解決と読み込みプロセスをカスタマイズするために Node.js によって呼び出される関数です。エクスポートされた関数は、特定の名前とシグネチャを持ち、名前付きエクスポートとしてエクスポートする必要があります。
export async function initialize({ number, port }) {
// `register` からデータを受け取ります。
}
export async function resolve(specifier, context, nextResolve) {
// `import` または `require` の specifier を受け取り、URL に解決します。
}
export async function load(url, context, nextLoad) {
// 解決された URL を受け取り、評価されるソースコードを返します。
}
非同期フックは、アプリケーションコードが実行されるメインスレッドから隔離された別のスレッドで実行されます。つまり、それは異なる realm です。フックスレッドはメインスレッドによっていつでも終了される可能性があるため、( console.log
のような) 非同期操作が完了することを当てにしないでください。それらはデフォルトで子ワーカーに継承されます。
module.registerHooks()
で受け入れられる同期フック
追加: v23.5.0
module.registerHooks()
メソッドは同期フック関数を受け入れます。フックの実装者が module.registerHooks()
の呼び出し前に初期化コードを直接実行できるため、initialize()
はサポートされておらず、必要もありません。
function resolve(specifier, context, nextResolve) {
// `import` または `require` の specifier を受け取り、URL に解決します。
}
function load(url, context, nextLoad) {
// 解決された URL を受け取り、評価されるソースコードを返します。
}
同期フックは、モジュールがロードされるのと同じスレッドおよび同じ realm で実行されます。非同期フックとは異なり、デフォルトでは子ワーカー スレッドに継承されませんが、フックが --import
または --require
によってプリロードされたファイルを使用して登録されている場合、子ワーカー スレッドは process.execArgv
の継承によってプリロードされたスクリプトを継承できます。詳細については、Worker
のドキュメント を参照してください。
同期フックでは、ユーザーはモジュール コードの console.log()
が完了するのと同じように console.log()
が完了することを期待できます。
フックの規約
フックは、カスタム (ユーザーが提供する) フックと、常に存在するデフォルトのフックの 1 つだけで構成される場合でも、チェーンの一部です。フック関数はネストします。各関数は常にプレーン オブジェクトを返し、各関数が後続のローダーのフックへの参照である next<hookName>()
を呼び出す結果として (LIFO 順で) チェーンが発生します。
必要なプロパティのない値を返すフックは、例外をトリガーします。next<hookName>()
を呼び出さずに かつ shortCircuit: true
を返さずに返すフックも例外をトリガーします。これらのエラーは、チェーンの意図しない中断を防ぐのに役立ちます。フックがあなたのフックで意図的に終了することを通知するには、フックから shortCircuit: true
を返します。
initialize()
Added in: v20.6.0, v18.19.0
[Stable: 1 - Experimental]
Stable: 1 Stability: 1.2 - リリース候補
data
<any>register(loader, import.meta.url, { data })
からのデータ。
initialize
フックは register
によってのみ受け入れられます。同期フックの初期化は registerHooks()
の呼び出し前に直接実行できるため、registerHooks()
はそれをサポートする必要もありません。
initialize
フックは、フックモジュールが初期化されるときにフックスレッドで実行されるカスタム関数を定義する方法を提供します。初期化は、フックモジュールが register
を介して登録されるときに発生します。
このフックは、ポートやその他の転送可能なオブジェクトを含む、register
の呼び出しからデータを受け取ることができます。initialize
の戻り値は、<Promise> にすることができます。その場合、メインアプリケーションスレッドの実行が再開される前に、それが待機されます。
モジュールカスタマイズコード:
// path-to-my-hooks.js
export async function initialize({ number, port }) {
port.postMessage(`increment: ${number + 1}`)
}
呼び出し側のコード:
import assert from 'node:assert'
import { register } from 'node:module'
import { MessageChannel } from 'node:worker_threads'
// この例では、メッセージチャネルを使用して、メイン(アプリケーション)スレッドと
// フックスレッドで実行されているフック間で通信する方法を示しています。
// `port2` を `initialize` フックに送信することで行います。
const { port1, port2 } = new MessageChannel()
port1.on('message', msg => {
assert.strictEqual(msg, 'increment: 2')
})
port1.unref()
register('./path-to-my-hooks.js', {
parentURL: import.meta.url,
data: { number: 1, port: port2 },
transferList: [port2],
})
const assert = require('node:assert')
const { register } = require('node:module')
const { pathToFileURL } = require('node:url')
const { MessageChannel } = require('node:worker_threads')
// この例では、メッセージチャネルを使用して、メイン(アプリケーション)スレッドと
// フックスレッドで実行されているフック間で通信する方法を示しています。
// `port2` を `initialize` フックに送信することで行います。
const { port1, port2 } = new MessageChannel()
port1.on('message', msg => {
assert.strictEqual(msg, 'increment: 2')
})
port1.unref()
register('./path-to-my-hooks.js', {
parentURL: pathToFileURL(__filename),
data: { number: 1, port: port2 },
transferList: [port2],
})
resolve(specifier, context, nextResolve)
[履歴]
バージョン | 変更点 |
---|---|
v23.5.0 | 同期およびスレッド内フックのサポートを追加。 |
v21.0.0, v20.10.0, v18.19.0 | プロパティcontext.importAssertions がcontext.importAttributes に置き換えられました。古い名前を使用することはまだサポートされており、実験的な警告が出力されます。 |
v18.6.0, v16.17.0 | resolve フックのチェーンをサポートしました。各フックは、nextResolve() を呼び出すか、またはその戻り値にshortCircuit プロパティをtrue に設定する必要があります。 |
v17.1.0, v16.14.0 | インポートアサーションのサポートを追加。 |
specifier
<string>context
<Object>conditions
<string[]> 関連するpackage.json
のエクスポート条件importAttributes
<Object> インポートするモジュールの属性を表すキーと値のペアのオブジェクトparentURL
<string> | <undefined> これをインポートしているモジュール。これが Node.js のエントリーポイントである場合は undefined
nextResolve
<Function> チェーン内の後続のresolve
フック、または最後のユーザー指定のresolve
フック後の Node.js のデフォルトresolve
フック戻り値: <Object> | <Promise> 非同期バージョンは、以下のプロパティを含むオブジェクト、またはそのようなオブジェクトに解決される
Promise
を受け取ります。同期バージョンは、同期的に返されるオブジェクトのみを受け入れます。format
<string> | <null> | <undefined> ロードフックへのヒント(無視される可能性があります)'builtin' | 'commonjs' | 'json' | 'module' | 'wasm'
importAttributes
<Object> | <undefined> モジュールをキャッシュするときに使用するインポート属性 (オプション。除外された場合は入力が使用されます)shortCircuit
<undefined> | <boolean> このフックがresolve
フックのチェーンを終了させる意図があるというシグナル。デフォルト:false
url
<string> この入力が解決する絶対 URL
resolve
フックチェーンは、Node.js に特定のimport
ステートメントまたは式、あるいはrequire
呼び出しをどこで見つけてキャッシュするかを伝える役割があります。オプションで、load
フックへのヒントとしてフォーマット (例: 'module'
) を返すことができます。フォーマットが指定されている場合、最終的なformat
値を提供する責任は最終的にload
フックにあり (resolve
が提供するヒントを無視してもかまいません)、resolve
がformat
を提供する場合、Node.js のデフォルトload
フックに値を渡すだけの場合でも、カスタムload
フックが必要です。
インポート型属性は、ロードされたモジュールを内部モジュールキャッシュに保存するためのキャッシュキーの一部です。resolve
フックは、モジュールをソースコードに存在するものとは異なる属性でキャッシュする必要がある場合に、importAttributes
オブジェクトを返す役割があります。
context
のconditions
プロパティは、この解決リクエストのパッケージエクスポート条件を一致させるために使用される条件の配列です。これらは、他の場所での条件付きマッピングの検索や、デフォルトの解決ロジックを呼び出すときのリストの変更に使用できます。
現在のパッケージエクスポート条件は、常にフックに渡されるcontext.conditions
配列に含まれています。defaultResolve
を呼び出すときに、デフォルトの Node.js モジュール指定子解決動作を保証するには、resolve
フックに最初に渡されたcontext.conditions
配列のすべての要素が、それに渡されるcontext.conditions
配列に含まれている必要があります。
// module.register()で受け入れられる非同期バージョン。
export async function resolve(specifier, context, nextResolve) {
const { parentURL = null } = context
if (Math.random() > 0.5) {
// 何らかの条件。
// 一部の指定子またはすべての指定子に対して、解決のためのカスタムロジックを実行します。
// 常に{url: <string>}の形式のオブジェクトを返します。
return {
shortCircuit: true,
url: parentURL ? new URL(specifier, parentURL).href : new URL(specifier).href,
}
}
if (Math.random() < 0.5) {
// 別の条件。
// `defaultResolve`を呼び出すとき、引数を変更できます。この場合、条件付きエクスポートを一致させるための別の値を追加します。
return nextResolve(specifier, {
...context,
conditions: [...context.conditions, 'another-condition'],
})
}
// チェーン内の次のフックに委ねます。これは、これが最後のユーザー指定のローダーの場合、Node.jsのデフォルトの解決になります。
return nextResolve(specifier)
}
// module.registerHooks()で受け入れられる同期バージョン。
function resolve(specifier, context, nextResolve) {
// 上記の非同期resolve()と同様。非同期ロジックがないため。
}
load(url, context, nextLoad)
[履歴]
バージョン | 変更点 |
---|---|
v23.5.0 | 同期およびインスレッドバージョンをサポート。 |
v20.6.0 | commonjs フォーマットの source をサポート。 |
v18.6.0, v16.17.0 | load フックのチェーンをサポート。各フックは nextLoad() を呼び出すか、または返り値に shortCircuit プロパティを true に設定する必要があります。 |
url
<string>resolve
チェーンによって返された URLcontext
<Object>conditions
<string[]> 関連するpackage.json
のエクスポート条件format
<string> | <null> | <undefined> オプションでresolve
フックチェーンによって提供されるフォーマットimportAttributes
<Object>
nextLoad
<Function> チェーン内の後続のload
フック、またはユーザー提供の最後のload
フックの後の Node.js のデフォルトのload
フック返り値: <Object> | <Promise> 非同期バージョンは、次のプロパティを含むオブジェクト、またはそのようなオブジェクトに解決される
Promise
のいずれかを取ります。同期バージョンは、同期的に返されるオブジェクトのみを受け入れます。format
<string>shortCircuit
<undefined> | <boolean> このフックがload
フックのチェーンを終了させる意図があることを示すシグナル。デフォルト:false
source
<string> | <ArrayBuffer> | <TypedArray> Node.js が評価するためのソース
load
フックは、URL をどのように解釈し、取得し、解析するかを決定するカスタムメソッドを定義する方法を提供します。また、インポート属性を検証する責任も負います。
format
の最終値は、次のいずれかである必要があります。
format | 説明 | load によって返される source の許容可能な型 |
---|---|---|
'builtin' | Node.js 組み込みモジュールをロード | 該当なし |
'commonjs' | Node.js CommonJS モジュールをロード | { string , ArrayBuffer , TypedArray , null , undefined } |
'json' | JSON ファイルをロード | { string , ArrayBuffer , TypedArray } |
'module' | ES モジュールをロード | { string , ArrayBuffer , TypedArray } |
'wasm' | WebAssembly モジュールをロード | { ArrayBuffer , TypedArray } |
source
の値は、現在 Node.js の組み込み (コア) モジュールの値を置き換えることができないため、'builtin'
型では無視されます。
非同期 load
フックにおける注意点
非同期の load
フックを使用する場合、'commonjs'
に対して source
を省略するか提供するかで、非常に異なる影響があります。
source
が提供される場合、このモジュールからのすべてのrequire
呼び出しは、登録されたresolve
およびload
フックを持つ ESM ローダーによって処理されます。このモジュールからのすべてのrequire.resolve
呼び出しは、登録されたresolve
フックを持つ ESM ローダーによって処理されます。CommonJS API のサブセットのみが利用可能となり(例:require.extensions
、require.cache
、require.resolve.paths
はなく)、CommonJS モジュールローダーへのモンキーパッチは適用されません。source
が未定義またはnull
の場合、CommonJS モジュールローダーによって処理され、require
/require.resolve
呼び出しは登録されたフックを通過しません。nullish のsource
に対するこの動作は一時的なものであり、将来は nullish のsource
はサポートされません。
これらの注意点は、同期 load
フックには適用されません。その場合、カスタマイズされた CommonJS モジュールで利用可能な CommonJS API の完全なセットが提供され、require
/ require.resolve
は常に登録されたフックを通過します。
Node.js の内部非同期 load
実装は、load
チェーンの最後のフックの next
の値であり、下位互換性のために format
が 'commonjs'
の場合、source
に対して null
を返します。以下は、非デフォルトの動作を使用するようにオプトインするフックの例です。
import { readFile } from 'node:fs/promises'
// module.register() で受け入れられる非同期バージョン。この修正は必要ありません
// module.registerSync() で受け入れられる同期バージョン。
export async function load(url, context, nextLoad) {
const result = await nextLoad(url, context)
if (result.format === 'commonjs') {
result.source ??= await readFile(new URL(result.responseURL ?? url))
}
return result
}
これも同期 load
フックには適用されません。その場合、返される source
には、モジュール形式に関係なく、次のフックによってロードされたソースコードが含まれます。
- 特定の
ArrayBuffer
オブジェクトは、SharedArrayBuffer
です。 - 特定の
TypedArray
オブジェクトは、Uint8Array
です。
テキストベースの形式(つまり、'json'
、'module'
)の source
値が文字列でない場合、util.TextDecoder
を使用して文字列に変換されます。
load
フックは、解決された URL のソースコードを取得するためのカスタムメソッドを定義する方法を提供します。これにより、ローダーはディスクからファイルを読み取るのを潜在的に回避できます。また、認識されない形式をサポートされている形式にマッピングするために使用することもできます。たとえば、yaml
を module
にマッピングできます。
// module.register() で受け入れられる非同期バージョン。
export async function load(url, context, nextLoad) {
const { format } = context
if (Math.random() > 0.5) {
// 何らかの条件
/*
一部またはすべての URL について、ソースを取得するためのカスタムロジックを実行します。
常に {
format: <string>,
source: <string|buffer>,
} の形式のオブジェクトを返します。
*/
return {
format,
shortCircuit: true,
source: '...',
}
}
// チェーン内の次のフックに処理を委ねます。
return nextLoad(url)
}
// module.registerHooks() で受け入れられる同期バージョン。
function load(url, context, nextLoad) {
// 上記の非同期 load() と同様。非同期ロジックがないため。
}
より高度なシナリオでは、これをサポートされていないソースをサポートされているソースに変換するためにも使用できます(下記の 例 を参照)。
例
さまざまなモジュールカスタマイズフックを組み合わせて使用することで、Node.js のコードの読み込みと評価の動作を広範囲にカスタマイズできます。
HTTPS からのインポート
以下のフックは、そのような指定子に対する基本的なサポートを有効にするためのフックを登録します。これは Node.js のコア機能の大幅な改善に見えるかもしれませんが、これらのフックを実際に使用するには大きな欠点があります。パフォーマンスがディスクからのファイルの読み込みよりもはるかに遅く、キャッシュがなく、セキュリティもありません。
// https-hooks.mjs
import { get } from 'node:https'
export function load(url, context, nextLoad) {
// ネットワーク経由で読み込まれるJavaScriptの場合、フェッチして
// それを返す必要があります。
if (url.startsWith('https://')) {
return new Promise((resolve, reject) => {
get(url, res => {
let data = ''
res.setEncoding('utf8')
res.on('data', chunk => (data += chunk))
res.on('end', () =>
resolve({
// この例では、ネットワークから提供されるすべてのJavaScriptがESモジュール
// コードであると仮定しています。
format: 'module',
shortCircuit: true,
source: data,
})
)
}).on('error', err => reject(err))
})
}
// 他のすべてのURLはNode.jsに処理させます。
return nextLoad(url)
}
// main.mjs
import { VERSION } from 'https://coffeescript.org/browser-compiler-modern/coffeescript.js'
console.log(VERSION)
上記のフックモジュールを使用し、node --import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; register(pathToFileURL("./https-hooks.mjs"));' ./main.mjs
を実行すると、main.mjs
の URL にあるモジュールに従って、現在の CoffeeScript のバージョンが出力されます。
トランスパイル
Node.js が理解できない形式のソースは、load
フックを使用して JavaScript に変換できます。
これは、Node.js を実行する前にソースファイルをトランスパイルするよりもパフォーマンスが劣ります。トランスパイラーフックは、開発およびテスト目的でのみ使用する必要があります。
非同期バージョン
// coffeescript-hooks.mjs
import { readFile } from 'node:fs/promises'
import { dirname, extname, resolve as resolvePath } from 'node:path'
import { cwd } from 'node:process'
import { fileURLToPath, pathToFileURL } from 'node:url'
import coffeescript from 'coffeescript'
const extensionsRegex = /\.(coffee|litcoffee|coffee\.md)$/
export async function load(url, context, nextLoad) {
if (extensionsRegex.test(url)) {
// CoffeeScriptファイルは CommonJS または ES モジュールのいずれかである可能性があるため、
// Node.js では CoffeeScript ファイルを同じ場所にある .js ファイルと同様に扱いたい。
// Node.js が任意の .js ファイルをどのように解釈するかを判断するには、
// ファイルシステムを検索して、最も近い親の package.json ファイルを探し、
// その "type" フィールドを読み取る。
const format = await getPackageType(url)
const { source: rawSource } = await nextLoad(url, { ...context, format })
// このフックは、すべてのインポートされた CoffeeScript ファイルに対して、
// CoffeeScript ソースコードを JavaScript ソースコードに変換する。
const transformedSource = coffeescript.compile(rawSource.toString(), url)
return {
format,
shortCircuit: true,
source: transformedSource,
}
}
// その他すべての URL は Node.js に処理させる。
return nextLoad(url)
}
async function getPackageType(url) {
// `url` は、load() フックから解決された URL が渡された最初の反復処理中にのみファイルパスになる
// load() からの実際のファイルパスには、仕様で要求されているため、ファイル拡張子が含まれる
// `url` にファイル拡張子が含まれているかどうかのこの単純な truthy チェックは、
// ほとんどのプロジェクトで機能するが、いくつかのエッジケース (拡張子のないファイルや、末尾にスペースがある URL など) はカバーしない
const isFilePath = !!extname(url)
// ファイルパスである場合は、それが存在するディレクトリを取得する
const dir = isFilePath ? dirname(fileURLToPath(url)) : url
// 同じディレクトリにある package.json へのファイルパスを構成する
// これは存在するかもしれないし、存在しないかもしれない
const packagePath = resolvePath(dir, 'package.json')
// 存在する可能性のある package.json を読み込もうとする
const type = await readFile(packagePath, { encoding: 'utf8' })
.then(filestring => JSON.parse(filestring).type)
.catch(err => {
if (err?.code !== 'ENOENT') console.error(err)
})
// package.json が存在し、値を持つ `type` フィールドが含まれている場合は、完了
if (type) return type
// そうでない場合(ルートにない場合)、次の上位ディレクトリのチェックを続行する
// ルートの場合は停止して false を返す
return dir.length > 1 && getPackageType(resolvePath(dir, '..'))
}
Synchronous version
// coffeescript-sync-hooks.mjs
import { readFileSync } from 'node:fs/promises'
import { registerHooks } from 'node:module'
import { dirname, extname, resolve as resolvePath } from 'node:path'
import { cwd } from 'node:process'
import { fileURLToPath, pathToFileURL } from 'node:url'
import coffeescript from 'coffeescript'
const extensionsRegex = /\.(coffee|litcoffee|coffee\.md)$/
function load(url, context, nextLoad) {
if (extensionsRegex.test(url)) {
const format = getPackageType(url)
const { source: rawSource } = nextLoad(url, { ...context, format })
const transformedSource = coffeescript.compile(rawSource.toString(), url)
return {
format,
shortCircuit: true,
source: transformedSource,
}
}
return nextLoad(url)
}
function getPackageType(url) {
const isFilePath = !!extname(url)
const dir = isFilePath ? dirname(fileURLToPath(url)) : url
const packagePath = resolvePath(dir, 'package.json')
let type
try {
const filestring = readFileSync(packagePath, { encoding: 'utf8' })
type = JSON.parse(filestring).type
} catch (err) {
if (err?.code !== 'ENOENT') console.error(err)
}
if (type) return type
return dir.length > 1 && getPackageType(resolvePath(dir, '..'))
}
registerHooks({ load })
Running hooks
# main.coffee {#maincoffee}
import { scream } from './scream.coffee'
console.log scream 'hello, world'
import { version } from 'node:process'
console.log "Brought to you by Node.js version #{version}"
# scream.coffee {#screamcoffee}
export scream = (str) -> str.toUpperCase()
上記のフックモジュールを使用すると、node --import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; register(pathToFileURL("./coffeescript-hooks.mjs"));' ./main.coffee
または node --import ./coffeescript-sync-hooks.mjs ./main.coffee
を実行すると、main.coffee
はそのソースコードがディスクからロードされた後、Node.js がそれを実行する前に JavaScript に変換されます。また、ロードされたファイルの import
ステートメントを介して参照される .coffee
、.litcoffee
、または .coffee.md
ファイルについても同様です。
インポートマップ
前の 2 つの例では、load
フックを定義しました。これは、resolve
フックの例です。このフックモジュールは、どの指定子を他の URL にオーバーライドするかを定義するimport-map.json
ファイルを読み取ります(これは、「インポートマップ」仕様の小さなサブセットの非常に単純な実装です)。
非同期バージョン
// import-map-hooks.js
import fs from 'node:fs/promises'
const { imports } = JSON.parse(await fs.readFile('import-map.json'))
export async function resolve(specifier, context, nextResolve) {
if (Object.hasOwn(imports, specifier)) {
return nextResolve(imports[specifier], context)
}
return nextResolve(specifier, context)
}
同期バージョン
// import-map-sync-hooks.js
import fs from 'node:fs/promises'
import module from 'node:module'
const { imports } = JSON.parse(fs.readFileSync('import-map.json', 'utf-8'))
function resolve(specifier, context, nextResolve) {
if (Object.hasOwn(imports, specifier)) {
return nextResolve(imports[specifier], context)
}
return nextResolve(specifier, context)
}
module.registerHooks({ resolve })
フックの使用
これらのファイルを使用します。
// main.js
import 'a-module'
// import-map.json
{
"imports": {
"a-module": "./some-module.js"
}
}
// some-module.js
console.log('some module!')
node --import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; register(pathToFileURL("./import-map-hooks.js"));' main.js
または node --import ./import-map-sync-hooks.js main.js
を実行すると、some module!
が出力されるはずです。
ソースマップ v3 のサポート
追加: v13.7.0, v12.17.0
ソースマップキャッシュを操作するためのヘルパー。このキャッシュは、ソースマップの解析が有効になり、モジュールのフッターにソースマップのインクルードディレクティブが見つかると設定されます。
ソースマップの解析を有効にするには、Node.js を--enable-source-maps
フラグを付けて実行するか、NODE_V8_COVERAGE=dir
を設定してコードカバレッジを有効にする必要があります。
// module.mjs
// ECMAScript モジュール内
import { findSourceMap, SourceMap } from 'node:module'
// module.cjs
// CommonJS モジュール内
const { findSourceMap, SourceMap } = require('node:module')
module.findSourceMap(path)
追加: v13.7.0, v12.17.0
path
<string>- 戻り値: <module.SourceMap> | <undefined> ソースマップが見つかった場合は
module.SourceMap
を返し、それ以外の場合はundefined
を返します。
path
は、対応するソースマップを取得する必要があるファイルの解決済みパスです。
クラス: module.SourceMap
追加: v13.7.0, v12.17.0
new SourceMap(payload[, { lineLengths }])
{#new-sourcemappayload-{-linelengths-}}
payload
<Object>lineLengths
<number[]>
新しい sourceMap
インスタンスを作成します。
payload
は、ソースマップ v3 形式 に一致するキーを持つオブジェクトです。
file
: <string>version
: <number>sources
: <string[]>sourcesContent
: <string[]>names
: <string[]>mappings
: <string>sourceRoot
: <string>
lineLengths
は、生成されたコードの各行の長さのオプションの配列です。
sourceMap.payload
- 戻り値: <Object>
SourceMap
インスタンスを構築するために使用されたペイロードのゲッター。
sourceMap.findEntry(lineOffset, columnOffset)
lineOffset
<number> 生成されたソースにおける、ゼロから始まる行番号オフセットcolumnOffset
<number> 生成されたソースにおける、ゼロから始まる列番号オフセット- Returns: <Object>
生成されたソースファイル内の行オフセットと列オフセットが与えられた場合、見つかれば元のファイル内の SourceMap 範囲を表すオブジェクトを返し、見つからなければ空のオブジェクトを返します。
返されるオブジェクトには、次のキーが含まれています。
- generatedLine: <number> 生成されたソース内の範囲の開始行オフセット
- generatedColumn: <number> 生成されたソース内の範囲の開始列オフセット
- originalSource: <string> SourceMap で報告されている、元のソースのファイル名
- originalLine: <number> 元のソース内の範囲の開始行オフセット
- originalColumn: <number> 元のソース内の範囲の開始列オフセット
- name: <string>
返される値は、エラーメッセージや CallSite オブジェクトに表示される 1 から始まる行番号と列番号ではなく、ゼロから始まるオフセットに基づいて、SourceMap に表示される生の範囲を表します。
エラーのスタックや CallSite オブジェクトによって報告される lineNumber と columnNumber から、対応する 1 から始まる行番号と列番号を取得するには、sourceMap.findOrigin(lineNumber, columnNumber)
を使用します。
sourceMap.findOrigin(lineNumber, columnNumber)
lineNumber
<number> 生成されたソース内の呼び出し元の 1 から始まる行番号columnNumber
<number> 生成されたソース内の呼び出し元の 1 から始まる列番号- 戻り値: <Object>
生成されたソース内の呼び出し元の 1 から始まる lineNumber
と columnNumber
が与えられた場合、対応する元のソース内の呼び出し元の場所を検索します。
指定された lineNumber
と columnNumber
がどのソースマップにも見つからない場合は、空のオブジェクトが返されます。それ以外の場合、返されるオブジェクトには次のキーが含まれます。
- name: <string> | <undefined> ソースマップで提供されていた場合、ソースマップ内の範囲の名前
- fileName: <string> ソースマップで報告されている元のソースのファイル名
- lineNumber: <number> 元のソース内の対応する呼び出し元の 1 から始まる行番号
- columnNumber: <number> 元のソース内の対応する呼び出し元の 1 から始まる列番号