Spec-Zone.ru › Node.js

Модули: CommonJS модули

Стабильность: 2 - Стабильно

CommonJS модули — это оригинальный способ упаковки кода JavaScript для Node.js. Node.js также поддерживает стандарт ECMAScript модулей, используемый браузерами и другими средами исполнения JavaScript.

В Node.js каждый файл рассматривается как отдельный модуль. Например, рассмотрим файл с именем foo.js:

const circle = require('./circle.js');
console.log(`The area of a circle of radius 4 is ${circle.area(4)}`); copy

В первой строке foo.js загружает модуль circle.js, который находится в той же директории, что и foo.js.

Вот содержимое circle.js:

const { PI } = Math;

exports.area = (r) => PI * r ** 2;

exports.circumference = (r) => 2 * PI * r; copy

Модуль circle.js экспортировал функции area() и circumference(). Функции и объекты добавляются в корень модуля путём указания дополнительных свойств в специальном объекте exports.

Переменные, локальные для модуля, будут приватными, потому что модуль обернут в функцию Node.js (см. обёртку модуля). В этом примере переменная PI является приватной для circle.js.

Свойству module.exports можно присвоить новое значение (например, функцию или объект).

В следующем коде bar.js использует модуль square, который экспортирует класс Square:

const Square = require('./square.js');
const mySquare = new Square(2);
console.log(`The area of mySquare is ${mySquare.area()}`); copy

Модуль square определён в square.js:

// Assigning to exports will not modify module, must use module.exports
module.exports = class Square {
  constructor(width) {
    this.width = width;
  }

  area() {
    return this.width ** 2;
  }
}; copy

Система CommonJS модулей реализована в module ядре модуля.

Включение

Node.js имеет две системы модулей: CommonJS модули и ECMAScript модули.

По умолчанию Node.js будет рассматривать следующие как CommonJS модули:

  • Файлы с расширением .cjs;

  • Файлы с расширением .js когда ближайший родительский файл package.json содержит поле верхнего уровня "type" со значением "commonjs".

  • Файлы с расширением .js или без расширения, когда ближайший родительский файл package.json не содержит поле верхнего уровня "type" или нет package.json в любой родительской папке; если файл не содержит синтаксис, который вызовет ошибку, если его обрабатывать как ES-модуль. Авторы пакетов должны включать поле "type", даже в пакетах, где все источники — CommonJS. Явное указание типа type пакета облегчит построение инструментами сборки и загрузчиками определение, как следует интерпретировать файлы в пакете.

  • Файлы с расширением, которое не является .mjs, .cjs, .json, .node, или .js (если ближайший родительский файл package.json содержит поле верхнего уровня "type" со значением "module", эти файлы будут распознаны как CommonJS модули только если они включаются с помощью require(), а не в качестве точки входа в программу в командной строке).

См. Определение системы модулей для получения более подробной информации.

Вызов require() всегда использует загрузчик CommonJS модулей. Вызов import() всегда использует загрузчик ECMAScript модулей.

Доступ к главному модулю

Когда файл запускается непосредственно из Node.js, require.main устанавливается в его module. Это означает, что можно определить, был ли файл запущен напрямую, проверив require.main === module.

Для файла foo.js, это будет true если запуск через node foo.js, но false если запуск через require('./foo').

Когда точка входа не является CommonJS модулем, require.main равно undefined, и главный модуль недоступен.

Рекомендации по работе с менеджерами пакетов

Семантика функции Node.js require() была разработана достаточно общо, чтобы поддерживать разумные структуры директорий. Программы-менеджеры пакетов, такие как dpkg, rpm, и npm, надеются, что им удастся создавать пакеты нативного кода из Node.js модулей без модификаций.

Ниже приведена рекомендуемая структура директорий:

Предположим, что мы хотим, чтобы папка /usr/lib/node/<some-package>/<some-version> содержала содержимое определённой версии пакета.

Пакеты могут зависеть друг от друга. Для установки пакета foo, может потребоваться установить определённую версию пакета bar. Пакет bar сам может иметь зависимости, которые в некоторых случаях могут сталкиваться или образовывать циклические зависимости.

Так как Node.js ищет realpath любого загружаемого модуля (то есть, он разрешает символические ссылки), а затем ищет их зависимости в папках node_modules, эта ситуация может быть решена следующей архитектурой:

  • /usr/lib/node/foo/1.2.3/: Содержимое пакета foo, версия 1.2.3.
  • /usr/lib/node/bar/4.3.2/: Содержимое пакета bar от которого зависит foo.
  • /usr/lib/node/foo/1.2.3/node_modules/bar: Символическая ссылка на /usr/lib/node/bar/4.3.2/.
  • /usr/lib/node/bar/4.3.2/node_modules/*: Символические ссылки на пакеты, от которых зависит bar.

Таким образом, даже если возникнет цикл или будут конфликты зависимостей, каждый модуль сможет получить версию своей зависимости, которую он сможет использовать.

Когда код в пакете foo выполняет require('bar'), он получит версию, которая символически связана с /usr/lib/node/foo/1.2.3/node_modules/bar. Затем, когда код в пакете bar вызывает require('quux'), он получит версию, символически связанную с /usr/lib/node/bar/4.3.2/node_modules/quux.

Кроме того, чтобы оптимизировать процесс поиска модулей, вместо размещения пакетов напрямую в /usr/lib/node, можно разместить их в /usr/lib/node_modules/<name>/<version>. Тогда Node.js не будет пытаться найти отсутствующие зависимости в /usr/node_modules или /node_modules.

Для того, чтобы сделать модули доступными в Node.js REPL, может быть полезно добавить папку /usr/lib/node_modules в переменную окружения $NODE_PATH.

Загрузка ECMAScript модулей с помощью require()

Расширение .mjs зарезервировано для ECMAScript модулей. В настоящее время, если флаг --experimental-require-module не используется, загрузка ECMAScript модуля с помощью require() вызовет ошибку ERR_REQUIRE_ESM, и пользователям нужно использовать import() вместо этого. Подробнее о том, какие файлы обрабатываются как ECMAScript модули, см. в разделе Определение системы модулей.

Если --experimental-require-module включено, и ECMAScript модуль, загружаемый с помощью require() , удовлетворяет следующим требованиям:

  • Модуль полностью синхронизирован (не содержит верхнеуровневых await); и
  • Выполняется одно из условий:
    1. Файл имеет расширение .mjs.
    2. Файл имеет расширение .js , и ближайший package.json содержит "type": "module"
    3. Файл имеет расширение .js , ближайший package.json не содержит "type": "commonjs", и --experimental-detect-module включено.

require() загрузит запрашиваемый модуль как ES Модуль и вернёт объект пространства имён модуля. В этом случае это аналогично динамическому import(), но выполняется синхронно и возвращает объект пространства имён напрямую.

MJS модули

// point.mjs
export function distance(a, b) { return (b.x - a.x) ** 2 + (b.y - a.y) ** 2; }
class Point {
  constructor(x, y) { this.x = x; this.y = y; }
}
export default Point;

CJS модули

const required = require('./point.mjs');
// [Module: null prototype] {
//   default: [class Point],
//   distance: [Function: distance]
// }
console.log(required);

(async () => {
  const imported = await import('./point.mjs');
  console.log(imported === required);  // true
})();

Если модуль, загружаемый с помощью require() , содержит верхнеуровневые await, или модульная граф, которую он imports, содержит верхнеуровневые await, будет брошена ошибка ERR_REQUIRE_ASYNC_MODULE. В этом случае пользователи должны загрузить асинхронный модуль с помощью import().

Если --experimental-print-required-tla включено, вместо того, чтобы вызывать ошибку ERR_REQUIRE_ASYNC_MODULE до оценки, Node.js оценит модуль, попытается найти верхнеуровневые ожидания и выведет их местоположение, чтобы помочь пользователям их исправить.

Всё вместе

Чтобы получить точное имя файла, который будет загружен при вызове require(), используйте функцию require.resolve().

Соединяя всё вышеизложенное, вот алгоритм высокого уровня того, что делает require():

require(X) from module at path Y
1. If X is a core module,
   a. return the core module
   b. STOP
2. If X begins with '/'
   a. set Y to be the file system root
3. If X begins with './' or '/' or '../'
   a. LOAD_AS_FILE(Y + X)
   b. LOAD_AS_DIRECTORY(Y + X)
   c. THROW "not found"
4. If X begins with '#'
   a. LOAD_PACKAGE_IMPORTS(X, dirname(Y))
5. LOAD_PACKAGE_SELF(X, dirname(Y))
6. LOAD_NODE_MODULES(X, dirname(Y))
7. THROW "not found"

MAYBE_DETECT_AND_LOAD(X)
1. If X parses as a CommonJS module, load X as a CommonJS module. STOP.
2. Else, if `--experimental-require-module` and `--experimental-detect-module` are
  enabled, and the source code of X can be parsed as ECMAScript module using
  DETECT_MODULE_SYNTAX defined in
  the ESM resolver,
  a. Load X as an ECMAScript module. STOP.
3. THROW the SyntaxError from attempting to parse X as CommonJS in 1. STOP.

LOAD_AS_FILE(X)
1. If X is a file, load X as its file extension format. STOP
2. If X.js is a file,
    a. Find the closest package scope SCOPE to X.
    b. If no scope was found
      1. MAYBE_DETECT_AND_LOAD(X.js)
    c. If the SCOPE/package.json contains "type" field,
      1. If the "type" field is "module", load X.js as an ECMAScript module. STOP.
      2. If the "type" field is "commonjs", load X.js as an CommonJS module. STOP.
    d. MAYBE_DETECT_AND_LOAD(X.js)
3. If X.json is a file, load X.json to a JavaScript Object. STOP
4. If X.node is a file, load X.node as binary addon. STOP

LOAD_INDEX(X)
1. If X/index.js is a file
    a. Find the closest package scope SCOPE to X.
    b. If no scope was found, load X/index.js as a CommonJS module. STOP.
    c. If the SCOPE/package.json contains "type" field,
      1. If the "type" field is "module", load X/index.js as an ECMAScript module. STOP.
      2. Else, load X/index.js as an CommonJS module. STOP.
2. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP
3. If X/index.node is a file, load X/index.node as binary addon. STOP

LOAD_AS_DIRECTORY(X)
1. If X/package.json is a file,
   a. Parse X/package.json, and look for "main" field.
   b. If "main" is a falsy value, GOTO 2.
   c. let M = X + (json main field)
   d. LOAD_AS_FILE(M)
   e. LOAD_INDEX(M)
   f. LOAD_INDEX(X) DEPRECATED
   g. THROW "not found"
2. LOAD_INDEX(X)

LOAD_NODE_MODULES(X, START)
1. let DIRS = NODE_MODULES_PATHS(START)
2. for each DIR in DIRS:
   a. LOAD_PACKAGE_EXPORTS(X, DIR)
   b. LOAD_AS_FILE(DIR/X)
   c. LOAD_AS_DIRECTORY(DIR/X)

NODE_MODULES_PATHS(START)
1. let PARTS = path split(START)
2. let I = count of PARTS - 1
3. let DIRS = []
4. while I >= 0,
   a. if PARTS[I] = "node_modules" CONTINUE
   b. DIR = path join(PARTS[0 .. I] + "node_modules")
   c. DIRS = DIR + DIRS
   d. let I = I - 1
5. return DIRS + GLOBAL_FOLDERS

LOAD_PACKAGE_IMPORTS(X, DIR)
1. Find the closest package scope SCOPE to DIR.
2. If no scope was found, return.
3. If the SCOPE/package.json "imports" is null or undefined, return.
4. let MATCH = PACKAGE_IMPORTS_RESOLVE(X, pathToFileURL(SCOPE),
  ["node", "require"]) defined in the ESM resolver.
5. RESOLVE_ESM_MATCH(MATCH).

LOAD_PACKAGE_EXPORTS(X, DIR)
1. Try to interpret X as a combination of NAME and SUBPATH where the name
   may have a @scope/ prefix and the subpath begins with a slash (`/`).
2. If X does not match this pattern or DIR/NAME/package.json is not a file,
   return.
3. Parse DIR/NAME/package.json, and look for "exports" field.
4. If "exports" is null or undefined, return.
5. let MATCH = PACKAGE_EXPORTS_RESOLVE(pathToFileURL(DIR/NAME), "." + SUBPATH,
   `package.json` "exports", ["node", "require"]) defined in the ESM resolver.
6. RESOLVE_ESM_MATCH(MATCH)

LOAD_PACKAGE_SELF(X, DIR)
1. Find the closest package scope SCOPE to DIR.
2. If no scope was found, return.
3. If the SCOPE/package.json "exports" is null or undefined, return.
4. If the SCOPE/package.json "name" is not the first segment of X, return.
5. let MATCH = PACKAGE_EXPORTS_RESOLVE(pathToFileURL(SCOPE),
   "." + X.slice("name".length), `package.json` "exports", ["node", "require"])
   defined in the ESM resolver.
6. RESOLVE_ESM_MATCH(MATCH)

RESOLVE_ESM_MATCH(MATCH)
1. let RESOLVED_PATH = fileURLToPath(MATCH)
2. If the file at RESOLVED_PATH exists, load RESOLVED_PATH as its extension
   format. STOP
3. THROW "not found"

Кэширование

Модули кэшируются после первого загрузки. Это означает (среди прочего), что каждый вызов require('foo') вернёт ровно тот же объект, если он будет соответствовать тому же файлу.

При условии, что require.cache не изменяется, несколько вызовов require('foo') не приведут к многократному выполнению кода модуля. Это важная функция. С ней можно возвращать "частично выполненные" объекты, что позволяет загружать транзитивные зависимости, даже если они вызывают циклы.

Чтобы заставить модуль выполнить код несколько раз, экспортируйте функцию и вызывайте её.

Ограничения кэширования модулей

Модули кэшируются на основе их разрешенного имени файла. Поскольку модули могут разрешаться до другого имени файла в зависимости от местоположения вызывающего модуля (загрузка из папок node_modules), нет гарантии, что require('foo') всегда вернёт ровно тот же объект, если он будет разрешён до различных файлов.

Кроме того, в системах с регистронезависимыми файлами или операционных системах разные разрешенные имена файлов могут указывать на один и тот же файл, но кэш всё равно будет рассматривать их как разные модули и перегружать файл несколько раз. Например, require('./foo') и require('./FOO') возвращают два разных объекта, независимо от того, являются ли ./foo и ./FOO одним и тем же файлом.

Встроенные модули

История
Версия Изменения
v16.0.0, v14.18.0

Добавлена поддержка импорта node: для require(...).

Node.js имеет несколько модулей, скомпилированных в двоичный файл. Эти модули описаны более подробно в других разделах этой документации.

Встроенные модули определены в исходном коде Node.js и расположены в папке lib/.

Встроенные модули можно идентифицировать по префиксу node:, в этом случае он обходит кэш require. Например, require('node:http') всегда вернёт встроенный модуль HTTP, даже если существует запись require.cache с таким же именем.

Некоторые встроенные модули всегда предпочтительно загружаются, если их идентификатор передан в require(). Например, require('http') всегда вернёт встроенный модуль HTTP, даже если существует файл с таким именем. Список встроенных модулей, которые можно загрузить без использования префикса node:, доступен по ссылке module.builtinModules.

Встроенные модули с обязательным префиксом node:

При загрузке через require(), некоторые встроенные модули должны быть запрошены с префиксом node:. Это необходимо, чтобы предотвратить конфликты между недавно добавленными встроенными модулями и пакетами пользовательского кода, которые уже используют это имя. В настоящее время встроенные модули, которые требуют префикс node:, включают:

  • node:sea
  • node:test
  • node:test/reporters

Циклы

При наличии циклических require() вызовов модуль может не завершить выполнение при возвращении.

Рассмотрим такую ситуацию:

a.js:

console.log('a starting');
exports.done = false;
const b = require('./b.js');
console.log('in a, b.done = %j', b.done);
exports.done = true;
console.log('a done'); copy

b.js:

console.log('b starting');
exports.done = false;
const a = require('./a.js');
console.log('in b, a.done = %j', a.done);
exports.done = true;
console.log('b done'); copy

main.js:

console.log('main starting');
const a = require('./a.js');
const b = require('./b.js');
console.log('in main, a.done = %j, b.done = %j', a.done, b.done); copy

Когда main.js загружает a.js, а a.js в свою очередь загружает b.js. В этот момент b.js пытается загрузить a.js. Для предотвращения бесконечной петли возвращается незавершенная копия объекта экспорта a.js модулю b.js. b.js затем завершает загрузку, и его объект exports предоставляется модулю a.js.

К моменту, когда main.js загрузит оба модуля, они оба будут завершены. Результат выполнения этой программы будет:

$ node main.js
main starting
a starting
b starting
in b, a.done = false
b done
in a, b.done = true
a done
in main, a.done = true, b.done = true copy

Требуется тщательное планирование, чтобы обеспечить корректную работу циклических зависимостей модулей в приложении.

Модули файлов

Если точное имя файла не найдено, Node.js попытается загрузить требуемый файл с добавленными расширениями: .js, .json и, наконец, .node. При загрузке файла с другим расширением (например, .cjs ), его полное имя должно быть передано в require(), включая расширение файла (например, require('./file.cjs')).

Файлы .json анализируются как текстовые файлы JSON, файлы .node интерпретируются как скомпилированные модули дополнений, загруженные с помощью process.dlopen(). Файлы с другими расширениями (или без расширения) анализируются как текстовые файлы JavaScript. Обратитесь к разделу Определение системы модулей для понимания используемой цели анализа.

Требуемый модуль с префиксом '/' - это абсолютный путь к файлу. Например, require('/home/marco/foo.js') загрузит файл по пути /home/marco/foo.js.

Требуемый модуль с префиксом './' относительный к файлу, вызывающему require(). То есть circle.js должен находиться в той же директории, что и foo.js, чтобы require('./circle') мог его найти.

Без ведущего префикса '/', './' или '../' для указания файла, модуль должен быть либо ядреным модулем, либо загружаться из папки node_modules.

Если указанный путь не существует, require() вызовет ошибку MODULE_NOT_FOUND.

Папки как модули

Устойчивость: 3 - Устарело: Используйте экспорт подпутей или импорт подпутей вместо этого.

Существует три способа передачи папки в require() в качестве аргумента.

Первый - создание файла package.json в корне папки, который определяет модуль main. Пример файла package.json может выглядеть так:

{ "name" : "some-library",
  "main" : "./lib/some-library.js" } copy

Если этот файл находится в папке по пути ./some-library, то require('./some-library') попытается загрузить ./some-library/lib/some-library.js.

Если файла package.json в директории нет или запись "main" отсутствует или не может быть разрешена, Node.js попытается загрузить файл index.js или index.node из этой директории. Например, если в предыдущем примере не было файла package.json, то require('./some-library') попытается загрузить:

  • ./some-library/index.js
  • ./some-library/index.node

Если эти попытки не увенчаются успехом, Node.js сообщит об отсутствии всего модуля с использованием стандартной ошибки:

Error: Cannot find module 'some-library' copy

Во всех трёх вышеперечисленных случаях вызов import('./some-library') приведёт к ошибке ERR_UNSUPPORTED_DIR_IMPORT. Использование пакета экспорт подпутей или импорт подпутей может предоставить те же преимущества организации контента, что и папки как модули, и работать как с require, так и с import.

Загрузка из папок node_modules

Если идентификатор модуля, переданный в require(), не является встроенным модулем, и не начинается с '/', '../' или './', Node.js начинает поиск в каталоге текущего модуля, добавляет /node_modules и пытается загрузить модуль из этого места. Node.js не добавит node_modules к пути, уже оканчивающемуся на node_modules.

Если модуль не найден, Node.js переходит к родительскому каталогу и так далее, пока не достигнет корня файловой системы.

Например, если файл по адресу '/home/ry/projects/foo.js' с именем require('bar.js'), Node.js будет искать в следующих местах в указанном порядке:

  • /home/ry/projects/node_modules/bar.js
  • /home/ry/node_modules/bar.js
  • /home/node_modules/bar.js
  • /node_modules/bar.js

Это позволяет программам локализовать свои зависимости, чтобы они не конфликтовали.

Можно загрузить конкретные файлы или подмодули, распределённые с модулем, добавив суффикс пути после имени модуля. Например, require('example-module/path/to/file') будет разрешать path/to/file относительно места расположения example-module. Путь с суффиксом следует тем же принципам разрешения модулей.

Загрузка из глобальных каталогов

Если переменная среды NODE_PATH установлена в список путей, разделённых двоеточием, Node.js будет искать модули в этих путях, если они не найдены в другом месте.

В Windows NODE_PATH разделяется точкой с запятой (;) вместо двоеточия.

NODE_PATH изначально был создан для поддержки загрузки модулей из различных путей до определения текущего алгоритма разрешения модулей .

NODE_PATH всё ещё поддерживается, но сейчас он менее необходим, поскольку экосистема Node.js разработала конвенцию для поиска зависимых модулей. Иногда развертывания, которые полагаются на NODE_PATH, демонстрируют неожиданное поведение, если пользователи не знают, что NODE_PATH должен быть установлен. Иногда зависимости модуля меняются, заставляя загружаться другую версию (или даже другой модуль), когда NODE_PATH исследуется.

Кроме того, Node.js будет искать в следующем списке GLOBAL_FOLDERS:

  • 1: $HOME/.node_modules
  • 2: $HOME/.node_libraries
  • 3: $PREFIX/lib/node

Где $HOME - домашний каталог пользователя, и $PREFIX - настроенная в Node.js папка node_prefix.

В основном это сделано по историческим причинам.

Настоятельно рекомендуется размещать зависимости в локальной папке node_modules для более быстрого и надёжного поиска.

Оборачивающая функция модуля

Перед выполнением кода модуля Node.js обернёт его в функцию-обёртку следующего вида:

(function(exports, require, module, __filename, __dirname) {
// Module code actually lives in here
}); copy

Это позволяет Node.js достичь нескольких целей:

  • Сохранение переменных верхнего уровня (определённых с помощью var, const, или let) внутри модуля, а не в глобальном объекте.
  • Предоставление некоторых переменных, похожих на глобальные, которые на самом деле являются специфическими для модуля, например:
    • Объекты module и exports, которые разработчик может использовать для экспорта значений из модуля.
    • Удобные переменные __filename и __dirname, содержащие абсолютный путь к файлу и каталогу модуля.
END_OF_DOCUMENT_MARKER

Область модуля

__dirname

Добавлен в: v0.1.27
  • <строка>

Имя каталога текущего модуля. Это то же самое, что и path.dirname() для __filename.

Пример: запуск node example.js из /Users/mjr

console.log(__dirname);
// Prints: /Users/mjr
console.log(path.dirname(__filename));
// Prints: /Users/mjr copy

__filename

Добавлен в: v0.0.1
  • <строка>

Имя файла текущего модуля. Это абсолютный путь к текущему файлу модуля с разрешёнными символическими ссылками.

Для основной программы это не обязательно совпадает с именем файла, используемым в командной строке.

См. __dirname для имени каталога текущего модуля.

Примеры:

Запуск node example.js из /Users/mjr

console.log(__filename);
// Prints: /Users/mjr/example.js
console.log(__dirname);
// Prints: /Users/mjr copy

Предположим два модуля: a и b, где b является зависимостью a и есть структура каталогов:

  • /Users/mjr/app/a.js
  • /Users/mjr/app/node_modules/b/b.js

Ссылки на __filename внутри b.js вернут /Users/mjr/app/node_modules/b/b.js, в то время как ссылки на __filename внутри a.js вернут /Users/mjr/app/a.js.

exports

Добавлен в: v0.1.12
  • <Объект>

Ссылка на module.exports, которая короче для набора. Подробности о том, когда использовать exports и когда module.exports, см. в разделе об экспорте с сокращением.

module

Добавлен в: v0.1.16
  • <модуль>

Ссылка на текущий модуль, см. раздел об объекте module объекта. В частности, module.exports используется для определения того, что экспортирует модуль, и что доступно через require().

require(id)

Добавлен в: v0.1.13
  • id <строка> имя или путь модуля
  • Возвращает: <любой> экспортируемое содержимое модуля

Используется для импорта модулей, JSON, и локальных файлов. Модули могут импортироваться из node_modules. Локальные модули и JSON-файлы можно импортировать, используя относительный путь (например, ./, ./foo, ./bar/baz, ../foo). Этот путь будет разрешён относительно каталога, указанного в __dirname (если он определён) или в текущей рабочей директории. Относительные пути в стиле POSIX разрешаются независимо от операционной системы, что означает, что вышеприведённые примеры будут работать в Windows так же, как и в системах Unix.

// Importing a local module with a path relative to the `__dirname` or current
// working directory. (On Windows, this would resolve to .\path\myLocalModule.)
const myLocalModule = require('./path/myLocalModule');

// Importing a JSON file:
const jsonData = require('./path/filename.json');

// Importing a module from node_modules or Node.js built-in module:
const crypto = require('node:crypto'); copy
require.cache
Добавлен в: v0.3.0
  • <Объект>

Модули кэшируются в этом объекте при их запросе. Удаление пары ключ-значение из этого объекта перезагрузит модуль при следующем require. Это не относится к нативным дополнениям, для которых перезагрузка приведёт к ошибке.

Также возможны добавление и замена записей. Этот кэш проверяется перед встроенными модулями, и если имя, соответствующее встроенному модулю, добавлено в кэш, только node:-префиксные вызовы require получат встроенный модуль. Используйте с осторожностью!

const assert = require('node:assert');
const realFs = require('node:fs');

const fakeFs = {};
require.cache.fs = { exports: fakeFs };

assert.strictEqual(require('fs'), fakeFs);
assert.strictEqual(require('node:fs'), realFs); copy
require.extensions
Добавлен в: v0.3.0Устарело начиная с: v0.10.6
Уровень стабильности: 0 - Устарело
  • <Объект>

Указывает require как обработать определённые расширения файлов.

Обрабатывать файлы с расширением .sjs как .js:

require.extensions['.sjs'] = require.extensions['.js']; copy

Устарело. В прошлом этот список использовался для загрузки не-JavaScript модулей в Node.js путём их компиляции по требованию. Однако на практике существуют лучшие способы сделать это, такие как загрузка модулей через другую программу Node.js или компиляция их в JavaScript заранее.

Избегайте использования require.extensions. Это может вызвать скрытые ошибки, и разрешение расширений замедляется с каждым зарегистрированным расширением.

require.main
Добавлен в: v0.1.17
  • <модуль> | <неопределён>

Объект Module представляющий скрипт-точку входа, загруженный при запуске процесса Node.js, или undefined если точка входа программы не является модулем CommonJS. См. "Доступ к главному модулю".

В скрипте entry.js:

console.log(require.main); copy
node entry.js copy
Module {
  id: '.',
  path: '/absolute/path/to',
  exports: {},
  filename: '/absolute/path/to/entry.js',
  loaded: false,
  children: [],
  paths:
   [ '/absolute/path/to/node_modules',
     '/absolute/path/node_modules',
     '/absolute/node_modules',
     '/node_modules' ] } copy
require.resolve(request[, options])
История
Версия Изменения
v8.9.0

Теперь поддерживается опция paths.

v0.3.0

Добавлен в: v0.3.0

  • request <строка> Путь модуля для разрешения.
  • options <Объект>
    • paths <массив строк> Пути для разрешения расположения модуля. Если присутствуют, эти пути используются вместо стандартных путей разрешения, за исключением GLOBAL_FOLDERS, как $HOME/.node_modules, которые всегда включены. Каждый из этих путей используется в качестве отправной точки для алгоритма разрешения модуля, что означает, что иерархия node_modules проверяется с этого расположения.
  • Возвращает: <строка>

Использует внутренние механизмы require() для поиска расположения модуля, но вместо загрузки модуля, возвращает только разрешённое имя файла.

Если модуль не найден, генерируется ошибка MODULE_NOT_FOUND.

require.resolve.paths(request)
Добавлен в: v8.9.0
  • request <строка> Путь модуля, пути поиска которого извлекаются.
  • Возвращает: <массив строк> | <null>

Возвращает массив, содержащий пути, которые проверялись при разрешении request или null, если строка request ссылается на основной модуль, например, http или fs.

Объект module

Добавлен в: v0.1.16
  • <Объект>

В каждом модуле свободная переменная module является ссылкой на объект, представляющий текущий модуль. Для удобства, module.exports также доступен через глобальную переменную модуля exports. module на самом деле не является глобальной, а локальной для каждого модуля.

module.children

Добавлен в: v0.1.16
  • <массив модулей>

Объекты модулей, необходимые этому модулю в первый раз.

module.exports

Добавлен в: v0.1.16
  • <Объект>

Объект module.exports, создаваемый системой Module. Иногда это неприемлемо; многие хотят, чтобы их модуль был экземпляром какого-либо класса. Для этого назначьте желаемый экспортируемый объект переменной module.exports. Назначение желаемого объекта в exports просто пересвяжет локальную переменную exports, что, вероятно, нежелательно.

Например, предположим, что мы создаём модуль a.js :

const EventEmitter = require('node:events');

module.exports = new EventEmitter();

// Do some work, and after some time emit
// the 'ready' event from the module itself.
setTimeout(() => {
  module.exports.emit('ready');
}, 1000); copy

Тогда в другом файле мы можем сделать следующее:

const a = require('./a');
a.on('ready', () => {
  console.log('module "a" is ready');
}); copy

Присвоение переменной module.exports должно быть выполнено немедленно. Это нельзя сделать в каких-либо коллбеках. Это не сработает:

x.js:

setTimeout(() => {
  module.exports = { a: 'hello' };
}, 0); copy

y.js:

const x = require('./x');
console.log(x.a); copy
exports сокращение
Добавлен в: v0.1.16

Переменная exports доступна в области видимости файла модуля и получает значение module.exports до оценки модуля.

Это позволяет сокращение, так что module.exports.f = ... можно записать более лаконично как exports.f = .... Однако, будьте внимательны, так как, как и любая переменная, если новое значение присваивается exports, оно больше не привязано к module.exports:

module.exports.hello = true; // Exported from require of module
exports = { hello: false };  // Not exported, only available in the module copy

Когда свойство module.exports полностью заменяется новым объектом, обычно переопределяется также и exports:

module.exports = exports = function Constructor() {
  // ... etc.
}; copy

Чтобы проиллюстрировать поведение, представьте себе эту гипотетическую реализацию require(), которая очень похожа на то, что фактически выполняет require():

function require(/* ... */) {
  const module = { exports: {} };
  ((module, exports) => {
    // Module code here. In this example, define a function.
    function someFunc() {}
    exports = someFunc;
    // At this point, exports is no longer a shortcut to module.exports, and
    // this module will still export an empty default object.
    module.exports = someFunc;
    // At this point, the module will now export someFunc, instead of the
    // default object.
  })(module, module.exports);
  return module.exports;
} copy

module.filename

Добавлен в: v0.1.16
  • <строка>

Полное имя файла модуля.

module.id

Добавлен в: v0.1.16
  • <строка>

Идентификатор модуля. Обычно это полное имя файла.

module.isPreloading

Добавлен в: v15.4.0, v14.17.0
  • Тип: <логическое значение> true если модуль выполняется во время фазы предварительной загрузки Node.js.

module.loaded

Добавлен в: v0.1.16
  • <логическое значение>

Загружен ли модуль или находится в процессе загрузки.

module.parent

Добавлен в: v0.1.16Устарело начиная с: v14.6.0, v12.19.0
Уровень стабильности: 0 - Устарело: Используйте require.main и module.children вместо этого.
  • <модуль> | <null> | <undefined>

Модуль, который сначала потребовал этого, или null если текущий модуль является точкой входа текущего процесса, или undefined если модуль был загружен чем-то, что не является модулем CommonJS (например, REPL или import).

module.path

Добавлен в: v11.14.0
  • <строка>

Имя каталога модуля. Обычно совпадает с path.dirname() module.id.

module.paths

Добавлен в: v0.4.0
  • <массив строк>

Пути поиска модуля.

module.require(id)

Добавлен в: v0.5.1
  • id <строка>
  • Возвращает: <любой> экспортируемое содержимое модуля

Метод module.require() предоставляет способ загрузки модуля так, как если бы require() вызывался из исходного модуля.

Для этого необходимо получить ссылку на объект module. Поскольку require() возвращает module.exports, и module обычно только доступна в коде конкретного модуля, её необходимо явно экспортировать для использования.

Объект Module

Этот раздел был перемещён в Модули: module базовый модуль.

  • module.builtinModules
  • module.createRequire(filename)
  • module.syncBuiltinESMExports()

Поддержка карт исходного кода v3

Этот раздел был перемещён в Модули: module базовый модуль.

  • module.findSourceMap(path)
  • Класс: module.SourceMap
    • new SourceMap(payload)
    • sourceMap.payload
    • sourceMap.findEntry(lineNumber, columnNumber)

© Joyent, Inc. and other Node contributors
Licensed under the MIT License.
Node.js is a trademark of Joyent, Inc. and is used with its permission.
We are not endorsed by or affiliated with Joyent.
https://nodejs.org/api/modules.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API