Почти все разработчики Node.js могут сказать вам, что выполняет функция `require ()`, но сколько из нас действительно знают, как она работает? Мы используем его каждый день для загрузки библиотек и модулей, но его поведение является для нас загадкой.
Из любопытства я углубился в базовый код узла, чтобы выяснить, что произошло под двигателем. Но это не единственная функция. Я нашел module.js в системе модулей узлов. Файл содержит удивительно мощный и относительно незнакомый модуль ядра, который управляет загрузкой, компиляцией и кэшированием каждого файла. `require ()`, его появление - только верхушка айсберга.
module.js
Кода -копия выглядит следующим образом:
Функциональный модуль (id, parent) {
this.id = id;
this.exports = {};
this.parent = родитель;
// ...
В module.js он в основном играет две роли внутри Node.js. Во -первых, он обеспечивает основу для всех модулей Node.js. Каждый файл является новым экземпляром базового модуля нового, и он все еще существует даже после запуска файла. Вот почему мы можем прикрепить свойства к module.exports и вернуть их при необходимости.
Вторая основная задача этого модуля - обрабатывать механизм загрузки модуля узла. Независимая операция функции «потребовать», которую мы используем, на самом деле является абстрактным концептуальным модулем. Ревира, которая сама является просто простой инкапсуляцией в отношении функции модуля._LOAD. Этот метод загрузки обрабатывает фактическую загрузку каждого файла и начинает наше путешествие там.
Module._load
Кода -копия выглядит следующим образом:
Module._load = function (запрос, родитель, ismain) {
// 1. Проверьте модуль._CACHE для кэшированного модуля.
// 2. Создайте новый экземпляр модуля, если кэш пуст.
// 3. Сохраните его в кеш.
// 4. Вызов module.load () с данным именем файла.
// это позвонит module.compile () после прочтения содержимого файла.
// 5. Если была ошибка загрузки/анализ файла,
// Удалить плохой модуль из кэша
// 6. return module.exports
};
Module._Load отвечает за загрузку новых модулей и управляющие кеши модулей. Кэш, загруженный каждый модуль, уменьшает количество считываний избыточных файлов и может значительно ускорить ваше приложение. Кроме того, экземпляр общего модуля позволяет модулям с синглтонскими характеристиками оставаться в штате в проекте.
Если в кэше не существует модуля, Module._Load создаст новый базовый модуль для файла. Затем он сообщит модулю прочитать содержимое нового файла перед отправкой их в Module._compile. [1]
Если вы заметите шаг № 6 выше, вы увидите, что Module.exports был возвращен пользователю. Вот почему, когда вы определяете использование публичного интерфейса, вы используете экспорт и модуль. Я был удивлен, что здесь больше не было, но было бы лучше, если бы это было.
module._compile
Кода -копия выглядит следующим образом:
Module.prototype._compile = function (content, filename) {
// 1. Создать автономную функцию требует функции, которая вызывает модуль.
// 2. Прикрепите другие вспомогательные методы, которые требуются.
// 3. Окутает код JS в функцию, которая обеспечивает наши требования,
// модуль и т. Д. Переменные локально для модуля.
// 4. Запустить эту функцию
};
・ Здесь происходит настоящее чудо. Во -первых, для модуля создается специальная независимая функция для оперативных требований. Это необходимая нам функция и все знакомы. Сама функция-это просто инкапсуляция в модуле.
・ Tress (): загрузите внешний модуль
・ Require.resolve (): анализируйте название модуля на его абсолютный путь
・ Требуется. Мейн: Основной модуль
・ Require.cache: все кэшированные модули
・ ・ Require.
После того, как потребность будет готова, весь загруженный исходный код будет инкапсулирован в новую функцию, что позволяет ему принимать потребности, модуль, экспорт и все другие обнаженные переменные в качестве параметров. Это функция, созданная только для инкапсуляции модулей, чтобы предотвратить конфликты с средой Node.js.
Кода -копия выглядит следующим образом:
(Функция (экспорт, потребность, модуль, __filename, __dirname) {
// ваш код введен здесь!
});
Метод module._compile выполняется синхронно, поэтому вызов к модуле. Нагрузка может подождать только до тех пор, пока код не будет запускаться, и возвращает module.exprts пользователю.
в заключение
Таким образом, мы уже поняли полный кодекс потребностей и имеем предварительное понимание того, как он работает.
Если вы сделали это до конца, то вы готовы к последнему секрету: Tress ('Module'). Это правильно, сама система модуля может быть загружена через систему модуля. Зарождение. Это может показаться странным, но позволяет пользователю взаимодействовать с системами загрузки модулей, не углубляясь в ядро Node.js. Популярные модули все построены так. [2]
Если вы хотите узнать больше, пожалуйста, проверьте исходный код Module.js самостоятельно. Есть еще много вещей, которых вам будет достаточно, чтобы на некоторое время боли головы. Первый может сказать мне, что такое node_module_contexts "и почему он добавлен может получить бонусные баллы :)
[1] Метод Module._compile используется только для запуска файлов JavaScript. Файл JSON должен быть проанализирован через json.parse () и возвращен
[2] Тем не менее, оба модуля построены на частных методах модуля, таких как Module._Resolvelookuppaths и Module._findpath. Вы можете думать, что это не намного лучше ...