Node.js
Экспорт и потребление модулей
Поиск…
замечания
Хотя все в Node.js обычно выполняется асинхронно, require()
не является одной из этих вещей. Так как модули на практике нужно загружать только один раз, это операция блокировки и должна использоваться должным образом.
Модули кэшируются после первого их загрузки. Если вы хотите редактировать модуль в разработке, вам нужно будет удалить его запись в кеше модуля, чтобы использовать новые изменения. При этом, даже если модуль очищен от кеша модуля, сам модуль не является сборкой мусора, поэтому следует проявлять осторожность при его использовании в производственных средах.
Загрузка и использование модуля
Модуль может быть «импортирован», иначе «требуется» функцией require()
. Например, чтобы загрузить модуль http
который поставляется с Node.js, можно использовать следующее:
const http = require('http');
Помимо модулей, поставляемых вместе со средой выполнения, вам также могут потребоваться модули, установленные вами из числа npm, например express. Если вы уже установили express в своей системе через npm install express
, вы можете просто написать:
const express = require('express');
Вы также можете включить модули, которые вы написали сами, как часть вашего приложения. В этом случае включить файл с именем lib.js
в том же каталоге, что и текущий файл:
const mylib = require('./lib');
Обратите внимание, что вы можете опустить расширение, и предполагается, что .js
. После загрузки модуля переменная заполняется объектом, который содержит методы и свойства, опубликованные из требуемого файла. Полный пример:
const http = require('http');
// The `http` module has the property `STATUS_CODES`
console.log(http.STATUS_CODES[404]); // outputs 'Not Found'
// Also contains `createServer()`
http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write('<html><body>Module Test</body></html>');
res.end();
}).listen(80);
Создание модуля hello-world.js
Узел предоставляет интерфейс module.exports
для module.exports
функций и переменных другим файлам. Самый простой способ сделать это - экспортировать только один объект (функцию или переменную), как показано в первом примере.
привет-world.js
module.exports = function(subject) {
console.log('Hello ' + subject);
};
Если мы не хотим, чтобы весь экспорт был единственным объектом, мы можем экспортировать функции и переменные в качестве свойств объекта exports
. Эти три следующих примера демонстрируют это несколько по-разному:
- hello-venus.js: определение функции выполняется отдельно, затем добавляется как свойство
module.exports
- hello-jupiter.js: определения функций непосредственно помещаются как значение свойств
module.exports
- hello-mars.js: определение функции напрямую объявляется как свойство
exports
которое является короткой версиейmodule.exports
привет-venus.js
function hello(subject) {
console.log('Venus says Hello ' + subject);
}
module.exports = {
hello: hello
};
привет-jupiter.js
module.exports = {
hello: function(subject) {
console.log('Jupiter says hello ' + subject);
},
bye: function(subject) {
console.log('Jupiter says goodbye ' + subject);
}
};
привет-mars.js
exports.hello = function(subject) {
console.log('Mars says Hello ' + subject);
};
Модуль загрузки с именем каталога
У нас есть каталог с именем hello
который включает в себя следующие файлы:
index.js
// hello/index.js
module.exports = function(){
console.log('Hej');
};
main.js
// hello/main.js
// We can include the other files we've defined by using the `require()` method
var hw = require('./hello-world.js'),
hm = require('./hello-mars.js'),
hv = require('./hello-venus.js'),
hj = require('./hello-jupiter.js'),
hu = require('./index.js');
// Because we assigned our function to the entire `module.exports` object, we
// can use it directly
hw('World!'); // outputs "Hello World!"
// In this case, we assigned our function to the `hello` property of exports, so we must
// use that here too
hm.hello('Solar System!'); // outputs "Mars says Hello Solar System!"
// The result of assigning module.exports at once is the same as in hello-world.js
hv.hello('Milky Way!'); // outputs "Venus says Hello Milky Way!"
hj.hello('Universe!'); // outputs "Jupiter says hello Universe!"
hj.bye('Universe!'); // outputs "Jupiter says goodbye Universe!"
hu(); //output 'hej'
Недействительность кэша модуля
В процессе разработки вы можете обнаружить, что использование require()
на одном модуле несколько раз всегда возвращает тот же модуль, даже если вы внесли изменения в этот файл. Это связано с тем, что при первом загрузке модулей кэшируются, и любые последующие загрузки модулей загружаются из кеша.
Чтобы обойти эту проблему, вам нужно будет delete
запись в кеше. Например, если вы загрузили модуль:
var a = require('./a');
Затем вы можете удалить запись кэша:
var rpath = require.resolve('./a.js');
delete require.cache[rpath];
Затем снова потребуется модуль:
var a = require('./a');
Обратите внимание, что это не рекомендуется в процессе производства, поскольку delete
удаляет ссылку только на загруженный модуль, а не на загруженные данные. Модуль не собирает мусор, поэтому неправильное использование этой функции может привести к утечке памяти.
Создание собственных модулей
Вы также можете ссылаться на объект для публичного экспорта и непрерывного добавления методов к этому объекту:
const auth = module.exports = {}
const config = require('../config')
const request = require('request')
auth.email = function (data, callback) {
// Authenticate with an email address
}
auth.facebook = function (data, callback) {
// Authenticate with a Facebook account
}
auth.twitter = function (data, callback) {
// Authenticate with a Twitter account
}
auth.slack = function (data, callback) {
// Authenticate with a Slack account
}
auth.stack_overflow = function (data, callback) {
// Authenticate with a Stack Overflow account
}
Чтобы использовать любой из них, просто требуется модуль, как обычно:
const auth = require('./auth')
module.exports = function (req, res, next) {
auth.facebook(req.body, function (err, user) {
if (err) return next(err)
req.user = user
next()
})
}
Каждый модуль вводится только один раз
NodeJS выполняет модуль только в первый раз, когда вы его требуете. Любые дополнительные функции требуют повторного использования одного и того же объекта, поэтому в противном случае не будет выполняться код в модуле. Кроме того, Node кэширует модули в первый раз, когда они загружаются с использованием require. Это уменьшает количество чтения файлов и помогает ускорить работу приложения.
myModule.js
console.log(123) ;
exports.var1 = 4 ;
index.js
var a=require('./myModule') ; // Output 123
var b=require('./myModule') ; // No output
console.log(a.var1) ; // Output 4
console.log(b.var1) ; // Output 4
a.var2 = 5 ;
console.log(b.var2) ; // Output 5
Загрузка модуля из node_modules
Модулям может require
d без использования относительных путей, помещая их в специальный каталог node_modules
.
Например, чтобы require
модуль под названием foo
из файла index.js
, вы можете использовать следующую структуру каталогов:
index.js
\- node_modules
\- foo
|- foo.js
\- package.json
Модули должны быть размещены внутри каталога вместе с файлом package.json
. main
поле файла package.json
должно указывать на точку входа для вашего модуля - это файл, который импортируется, когда пользователи этого require('your-module')
. main
значения по умолчанию - index.js
если они не index.js
. Кроме того, вы можете ссылаться на файлы относительно вашего модуля, просто добавив относительный путь к require
вызова: require('your-module/path/to/file')
.
node_modules
также может require
d от node_modules
до иерархии файловой системы. Если у нас есть следующая структура каталогов:
my-project
\- node_modules
|- foo // the foo module
\- ...
\- baz // the baz module
\- node_modules
\- bar // the bar module
мы сможем require
модуль foo
из любого файла в bar
используя require('foo')
.
Обратите внимание, что узел будет соответствовать только самому модулю, находящемуся ближе всего к файлу в иерархии файловой системы, начиная с (текущий каталог файла / node_modules). Узел сопоставляет каталоги таким образом до корня файловой системы.
Вы можете либо установить новые модули из реестра npm, либо в другие реестры npm или создать свои собственные.
Папка как модуль
Модули можно разделить на многие .js-файлы в одной папке. Пример в папке my_module :
function_one.js
module.exports = function() {
return 1;
}
function_two.js
module.exports = function() {
return 2;
}
index.js
exports.f_one = require('./function_one.js');
exports.f_two = require('./function_two.js');
Модуль, подобный этому, используется, ссылаясь на него по имени папки:
var split_module = require('./my_module');
Обратите внимание, что если вам это необходимо, опустив ./
или любое указание пути к папке из аргумента функции require, Node попытается загрузить модуль из папки node_modules .
В качестве альтернативы вы можете создать в той же папке файл package.json
с этим содержимым:
{
"name": "my_module",
"main": "./your_main_entry_point.js"
}
Таким образом, вам не нужно указывать основной файл модуля «index».