Модули: CommonJS модули
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); и - Выполняется одно из условий:
- Файл имеет расширение
.mjs. - Файл имеет расширение
.js, и ближайшийpackage.jsonсодержит"type": "module" - Файл имеет расширение
.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 одним и тем же файлом.
Встроенные модули
Node.js имеет несколько модулей, скомпилированных в двоичный файл. Эти модули описаны более подробно в других разделах этой документации.
Встроенные модули определены в исходном коде Node.js и расположены в папке lib/.
Встроенные модули можно идентифицировать по префиксу node:, в этом случае он обходит кэш require. Например, require('node:http') всегда вернёт встроенный модуль HTTP, даже если существует запись require.cache с таким же именем.
Некоторые встроенные модули всегда предпочтительно загружаются, если их идентификатор передан в require(). Например, require('http') всегда вернёт встроенный модуль HTTP, даже если существует файл с таким именем. Список встроенных модулей, которые можно загрузить без использования префикса node:, доступен по ссылке module.builtinModules.
Встроенные модули с обязательным префиксом node:
При загрузке через require(), некоторые встроенные модули должны быть запрошены с префиксом node:. Это необходимо, чтобы предотвратить конфликты между недавно добавленными встроенными модулями и пакетами пользовательского кода, которые уже используют это имя. В настоящее время встроенные модули, которые требуют префикс node:, включают:
Циклы
При наличии циклических 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.
Папки как модули
Существует три способа передачи папки в 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, содержащие абсолютный путь к файлу и каталогу модуля.
- Объекты
Область модуля
__dirname
Имя каталога текущего модуля. Это то же самое, что и path.dirname() для __filename.
Пример: запуск node example.js из /Users/mjr
console.log(__dirname); // Prints: /Users/mjr console.log(path.dirname(__filename)); // Prints: /Users/mjr copy
__filename
Имя файла текущего модуля. Это абсолютный путь к текущему файлу модуля с разрешёнными символическими ссылками.
Для основной программы это не обязательно совпадает с именем файла, используемым в командной строке.
См. __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
Ссылка на module.exports, которая короче для набора. Подробности о том, когда использовать exports и когда module.exports, см. в разделе об экспорте с сокращением.
module
Ссылка на текущий модуль, см. раздел об объекте module объекта. В частности, module.exports используется для определения того, что экспортирует модуль, и что доступно через require().
require(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
Модули кэшируются в этом объекте при их запросе. Удаление пары ключ-значение из этого объекта перезагрузит модуль при следующем 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
Указывает require как обработать определённые расширения файлов.
Обрабатывать файлы с расширением .sjs как .js:
require.extensions['.sjs'] = require.extensions['.js']; copy
Устарело. В прошлом этот список использовался для загрузки не-JavaScript модулей в Node.js путём их компиляции по требованию. Однако на практике существуют лучшие способы сделать это, такие как загрузка модулей через другую программу Node.js или компиляция их в JavaScript заранее.
Избегайте использования require.extensions. Это может вызвать скрытые ошибки, и разрешение расширений замедляется с каждым зарегистрированным расширением.
require.main
Объект 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])
-
request<строка> Путь модуля для разрешения. -
options<Объект>-
paths<массив строк> Пути для разрешения расположения модуля. Если присутствуют, эти пути используются вместо стандартных путей разрешения, за исключением GLOBAL_FOLDERS, как$HOME/.node_modules, которые всегда включены. Каждый из этих путей используется в качестве отправной точки для алгоритма разрешения модуля, что означает, что иерархияnode_modulesпроверяется с этого расположения.
-
- Возвращает: <строка>
Использует внутренние механизмы require() для поиска расположения модуля, но вместо загрузки модуля, возвращает только разрешённое имя файла.
Если модуль не найден, генерируется ошибка MODULE_NOT_FOUND.
require.resolve.paths(request)
-
request<строка> Путь модуля, пути поиска которого извлекаются. - Возвращает: <массив строк> | <null>
Возвращает массив, содержащий пути, которые проверялись при разрешении request или null, если строка request ссылается на основной модуль, например, http или fs.
Объект module
В каждом модуле свободная переменная module является ссылкой на объект, представляющий текущий модуль. Для удобства, module.exports также доступен через глобальную переменную модуля exports. module на самом деле не является глобальной, а локальной для каждого модуля.
module.children
Объекты модулей, необходимые этому модулю в первый раз.
module.exports
Объект 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 сокращение
Переменная 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
Полное имя файла модуля.
module.id
Идентификатор модуля. Обычно это полное имя файла.
module.isPreloading
- Тип: <логическое значение>
trueесли модуль выполняется во время фазы предварительной загрузки Node.js.
module.loaded
Загружен ли модуль или находится в процессе загрузки.
module.parent
Модуль, который сначала потребовал этого, или null если текущий модуль является точкой входа текущего процесса, или undefined если модуль был загружен чем-то, что не является модулем CommonJS (например, REPL или import).
module.path
Имя каталога модуля. Обычно совпадает с path.dirname() module.id.
module.paths
Пути поиска модуля.
module.require(id)
Метод module.require() предоставляет способ загрузки модуля так, как если бы require() вызывался из исходного модуля.
Для этого необходимо получить ссылку на объект module. Поскольку require() возвращает module.exports, и module обычно только доступна в коде конкретного модуля, её необходимо явно экспортировать для использования.
Объект Module
Этот раздел был перемещён в Модули: module базовый модуль.
Поддержка карт исходного кода v3
Этот раздел был перемещён в Модули: module базовый модуль.
© 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