启用
¥Enabling
模块解析和加载可以通过以下方式自定义:
¥Module resolution and loading can be customized by:
-
使用来自
node:module
的register
方法注册导出一组异步钩子函数的文件,¥Registering a file which exports a set of asynchronous hook functions, using the
register
method fromnode:module
, -
使用来自
node:module
的registerHooks
方法注册一组同步钩子函数。¥Registering a set of synchronous hook functions using the
registerHooks
method fromnode:module
.
可以使用 --import
或 --require
标志在运行应用代码之前注册钩子:
¥The hooks can be registered before the application code is run by using the
--import
or --require
flag:
node --import ./register-hooks.js ./my-app.js
node --require ./register-hooks.js ./my-app.js
// register-hooks.js
// This file can only be require()-ed if it doesn't contain top-level await.
// Use module.register() to register asynchronous hooks in a dedicated thread.
import { register } from 'node:module';
register('./hooks.mjs', import.meta.url);
// register-hooks.js
const { register } = require('node:module');
const { pathToFileURL } = require('node:url');
// Use module.register() to register asynchronous hooks in a dedicated thread.
register('./hooks.mjs', pathToFileURL(__filename));
// Use module.registerHooks() to register synchronous hooks in the main thread.
import { registerHooks } from 'node:module';
registerHooks({
resolve(specifier, context, nextResolve) { /* implementation */ },
load(url, context, nextLoad) { /* implementation */ },
});
// Use module.registerHooks() to register synchronous hooks in the main thread.
const { registerHooks } = require('node:module');
registerHooks({
resolve(specifier, context, nextResolve) { /* implementation */ },
load(url, context, nextLoad) { /* implementation */ },
});
传递给 --import
或 --require
的文件也可以是从依赖导出的:
¥The file passed to --import
or --require
can also be an export from a dependency:
node --import some-package/register ./my-app.js
node --require some-package/register ./my-app.js
其中 some-package
有一个 "exports"
字段,定义 /register
导出以映射到调用 register()
的文件,如以下 register-hooks.js
示例。
¥Where some-package
has an "exports"
field defining the /register
export to map to a file that calls register()
, like the following register-hooks.js
example.
使用 --import
或 --require
可确保在导入任何应用文件之前注册钩子,包括应用的入口点以及默认情况下的任何工作线程。
¥Using --import
or --require
ensures that the hooks are registered before any
application files are imported, including the entry point of the application and for
any worker threads by default as well.
或者,可以从入口点调用 register()
和 registerHooks()
,但对于在注册钩子后应运行的任何 ESM 代码,必须使用动态 import()
。
¥Alternatively, register()
and registerHooks()
can be called from the entry point,
though dynamic import()
must be used for any ESM code that should be run after the hooks
are registered.
import { register } from 'node:module';
register('http-to-https', import.meta.url);
// Because this is a dynamic `import()`, the `http-to-https` hooks will run
// to handle `./my-app.js` and any other files it imports or requires.
await import('./my-app.js');
const { register } = require('node:module');
const { pathToFileURL } = require('node:url');
register('http-to-https', pathToFileURL(__filename));
// Because this is a dynamic `import()`, the `http-to-https` hooks will run
// to handle `./my-app.js` and any other files it imports or requires.
import('./my-app.js');
自定义钩子将针对注册后加载的任何模块以及它们通过 import
和内置 require
引用的模块运行。用户使用 module.createRequire()
创建的 require
函数只能由同步钩子自定义。
¥Customization hooks will run for any modules loaded later than the registration
and the modules they reference via import
and the built-in require
.
require
function created by users using module.createRequire()
can only be
customized by the synchronous hooks.
在此示例中,我们正在注册 http-to-https
钩子,但它们仅适用于随后导入的模块 - 在本例中,my-app.js
及其通过 import
或 CommonJS 依赖中的内置 require
引用的任何内容。
¥In this example, we are registering the http-to-https
hooks, but they will
only be available for subsequently imported modules — in this case, my-app.js
and anything it references via import
or built-in require
in CommonJS dependencies.
如果 import('./my-app.js')
是静态 import './my-app.js'
,则应用将在注册 http-to-https
钩子之前已加载。这是由于 ES 模块规范,其中静态导入首先从树的叶子进行评估,然后返回主干。my-app.js
内可以有静态导入,直到动态导入 my-app.js
后才会对其求值。
¥If the import('./my-app.js')
had instead been a static import './my-app.js'
, the
app would have already been loaded before the http-to-https
hooks were
registered. This due to the ES modules specification, where static imports are
evaluated from the leaves of the tree first, then back to the trunk. There can
be static imports within my-app.js
, which will not be evaluated until
my-app.js
is dynamically imported.
如果使用同步钩子,则支持使用 createRequire()
创建的 import
、require
和用户 require
。
¥If synchronous hooks are used, both import
, require
and user require
created
using createRequire()
are supported.
import { registerHooks, createRequire } from 'node:module';
registerHooks({ /* implementation of synchronous hooks */ });
const require = createRequire(import.meta.url);
// The synchronous hooks affect import, require() and user require() function
// created through createRequire().
await import('./my-app.js');
require('./my-app-2.js');
const { register, registerHooks } = require('node:module');
const { pathToFileURL } = require('node:url');
registerHooks({ /* implementation of synchronous hooks */ });
const userRequire = createRequire(__filename);
// The synchronous hooks affect import, require() and user require() function
// created through createRequire().
import('./my-app.js');
require('./my-app-2.js');
userRequire('./my-app-3.js');
最后,如果你只想在应用运行之前注册钩子,并且不想为此目的创建单独的文件,则可以将 data:
URL 传递给 --import
:
¥Finally, if all you want to do is register hooks before your app runs and you
don't want to create a separate file for that purpose, you can pass a data:
URL to --import
:
node --import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; register("http-to-https", pathToFileURL("./"));' ./my-app.js