导入中
import-in-the-middle 是一个模块加载拦截器,灵感来自
require-in-the-middle不过
具体针对无害环境管理模块。 事实上,它甚至可以在装入后修改模块
时间.
使用量
API 为
require-in-the-middle 尽可能密切跟踪默认
输出。 有低级的 addHook 财务报告和审定财务报表 removeHook 现有出口
不对模块进行任何过滤, 并将完整文件 URL 作为参数显示
到钩上。 请参看详细 API 文档的 Typescription 定义文件 .
您可以修改从任何给定的无害环境管理或CJS模块中导出的任何内容 进口到无害环境管理文件中,无论它们是静态进口还是 充满活力.
import { Hook } from 'import-in-the-middle'
import { foo } from 'package-i-want-to-modify'
console.log(foo) // whatever that module exported
Hook(['package-i-want-to-modify'], (exported, name, baseDir) => {
// `exported` is effectively `import * as exported from ${url}`
exported.foo += 1
})
console.log(foo) // 1 more than whatever that module exported
这需要使用无害环境管理装载机钩,可添加如下内容: 命令行选项.
node --loader=import-in-the-middle/hook.mjs my-app.mjs
自兹 --loader 您也可以通过节点程序注册装入器钩
module.register()
API (英语). 然而,为了能够钩住非动态进口商品,必须
在您的应用程序代码通过 --import 命令行选项.
my-loader.mjs
import * as module from 'module'
module.register('import-in-the-middle/hook.mjs', import.meta.url)
node --import=./my-loader.mjs ./my-code.mjs
在程序上注册装车钩时,可以通过列表
模块、文件 URL 或正则表达式 exclude 或特别
include 哪些模块被截取。 如果模块不可用, 则此功能将有所帮助
兼容装入器钩.
说明: 此特性与
{internals: true}钩子选项
import * as module from 'module'
// Exclude intercepting a specific module by name
module.register('import-in-the-middle/hook.mjs', import.meta.url, {
data: { exclude: ['package-i-want-to-exclude'] }
})
// Only intercept a specific module by name
module.register('import-in-the-middle/hook.mjs', import.meta.url, {
data: { include: ['package-i-want-to-include'] }
})
只截取钩状模块
说明: 这个特征是实验性的,不符合
{internals: true}钩子选项
如果你是的话 Hook“在导入所有模块之前进行,例如:
通过节点.js装入的模块 --import CLI 参数, 您可以配置
装入器只截取被锁定的模块 .
instrument.mjs
import { register } from 'module'
import { Hook, createAddHookMessageChannel } from 'import-in-the-middle'
const { registerOptions, waitForAllMessagesAcknowledged } = createAddHookMessageChannel()
register('import-in-the-middle/hook.mjs', import.meta.url, registerOptions)
Hook(['fs'], (exported, name, baseDir) => {
// Instrument the fs module
})
// Ensure that the loader has acknowledged all the modules
// before we allow execution to continue
await waitForAllMessagesAcknowledged()
my-app.mjs
import * as fs from 'fs'
// fs will be instrumented!
fs.readFileSync('file.txt')
node --import=./instrument.mjs ./my-app.mjs
发展基准
见 基准/README.md pR基准方法 如何在当地检查测量噪音.
同步加载车钩
在支持的节点.js版本上
module.registerHooks()
装载器可以运行 同步,在应用程序线索上,而不是在
独立线程 module.register() 用户。 运行内行删除
消息频道 : Hook() 登记器直接可见,所以
页:1 createAddHookMessageChannel 编号 : waitForAllMessagesAcknowledged 显示步骤
上文已无必要.
module.registerHooks() 在22.15.0/24.0.0中添加,但其同步负载
钩子拒绝了无效的普通JS source 装入器返回 require()编号
进入无害环境管理图,直到 节点/节点# 59929。运入的固定器
22.22.3、24.11.1、25.1.0和26.0.0; 早先的版本飞船
module.registerHooks() 但不能运行同步加载器。 使用
supportsSyncHooks() 以切换到此选项, 而不是手写版本检查 :
import { register, supportsSyncHooks } from 'import-in-the-middle/register-hooks.mjs'
if (supportsSyncHooks()) {
register({ include: ['package-i-want-to-include'] })
} else {
// Fall back to the asynchronous loader, e.g. module.register('import-in-the-middle/hook.mjs').
}
instrument.mjs
import { register } from 'import-in-the-middle/register-hooks.mjs'
import { Hook } from 'import-in-the-middle'
register({ include: ['package-i-want-to-include'] })
Hook(['package-i-want-to-include'], (exported, name, baseDir) => {
// Instrument the module
})
node --import=./instrument.mjs ./my-app.mjs
register() 接受相同的建议 include 编号 : exclude 选项为同步
加载器和投放到一个节点.js版本中 supportsSyncHooks() 实值 false。 。 。 .
自定义匹配 shouldInclude
改为 include 编号 : exclude 列表,您可以通过 shouldInclude(url, specifier)
以决定哪些模块被截取 。 它要求每一个决心
模块,包含已解析的 URL 和导入指定符;返回一个真实值到
截取模块。 如果上游地区接管裁决
页:1 include 编号 : exclude 选项被忽略.
当匹配不清晰地映射到光谱、文件 URL 和 正则表达式——例如自配置构建的匹配器,或 取决于比说明者更多的决定.
import { register } from 'import-in-the-middle/register-hooks.mjs'
register({
shouldInclude (url, specifier) {
return specifier === 'package-i-want-to-include' ||
url.includes('/node_modules/some-scope/')
}
})
上游只接收到URL和指定符,从没有解析出的文件路径.
因为 module.register() 转让 data 按结构排列到装入器线索
克隆——不能承担一个函数—— shouldInclude 支持同步
登记register-hooks.mjs上表所示),并用于构造于
装入器线程; 无法通过 data 同步选项
module.register('import-in-the-middle/hook.mjs', ...)。 。 。 .
选择退出 CJS 源代码
在节点22+上,当一个CJS模块通过无害环境管理翻译器和另一个模块被装入时
加载车钩提供了它的源(而不是离开它) null 将节点改为
土生土长, require() 调用 CJS 模块内使用
"module-sync" 输出条件失败 ERR_VM_MODULE_LINK_FAILURE工作时
围绕这个节点错误, import-in-the-middle 条形钩提供源
同步中的 CJS 模块需要链条, 强制节点使用其本地 CJS
正确处理这个的加载器 .
如果依靠下游装船钩看到(并采取行动)
CJS 模块在要求链中,您可以通过通过
disableCjsSourceStripping: true 在钩子配置。 继续工作
默认启用.
import { register } from 'import-in-the-middle/register-hooks.mjs'
register({
include: ['package-i-want-to-include'],
disableCjsSourceStripping: true
})
此选项为两个同步器所接受( S)register-hooks.mjs和
同步( a)module.register('import-in-the-middle/hook.mjs', ...)登记.
类型脚本模块
在 Node.js 版本上, 以本地方式剥取 TypeScript 类型( 那些曝光)
module.stripTypeScriptTypes(), (中文(简体) ),
= 22.13.0 / = 23.9.0 / = 24.0.0), (中文(简体) ),
import-in-the-middle拦截.ts, (中文(简体) ),.mts财务报告和审定财务报表.cts模块,就像他们的 JavaScript 对等。 这些类型是: 在读取模块导出前剥离, 所以只类型导出 (单位:千美元)export type, (中文(简体) ),export interface) 被拦截者不在 名称空间; 值导出为 .
// math.mts
export type Op = '+' | '-'
export function add (a: number, b: number): number {
return a + b
}
Hook(['./math.mts'], (exported) => {
// `exported.add` is interceptable; the `Op` type is not part of the namespace
})
在默认无法启用类型剥取的Node.js版本上,以
--experimental-strip-types。更早的版本
module.stripTypeScriptTypes() 保留类型脚本模块.
限制
- 您无法在模块中添加新导出 。 您只能修改已有的 .
- 对模块导出绑定时,如果修改为 钩,动态导入的模块被装入后不能被更改.
- 模块通过
require完全没有受到影响. - 一个模块的导出集 名称 被假定为终生稳定
过程.
import-in-the-middle读取模块的源头一次 输出和再利用将导出设定为同一 URL 的后期负载。 一个上游 返回 a 的加载器 各类出口 相同 URL 的呼叫 – 状态的编码加载器,或其输出变化为context已经.. 不支持,并且将使用第一个出口集的设备 装入。 异能变换(取出型号、AST仪器、变异器) 不受影响, 而实际模块仍然执行源其实际负载 返回; 只有可截取导出 名称 被纪念.