Работа с модулями

Последнее обновление: 21.11.2023

Рассмотрим некоторые аспекты работы с модулями в Node.js. Прежде всего надо отметить, что подключаемые модули кэшируются. В частности, в файле https://github.com/nodejs/node/blob/master/lib/internal/modules/cjs/loader.js есть такие строки:

const filename = Module._resolveFilename(request, parent, isMain);
  const cachedModule = Module._cache[filename];
  if (cachedModule !== undefined) {
    updateChildren(parent, cachedModule, true);
    if (!cachedModule.loaded) {
      const parseCachedModule = cjsParseCache.get(cachedModule);
      if (!parseCachedModule || parseCachedModule.loaded) {
        return getExportsForCircularRequire(cachedModule);
      }
      parseCachedModule.loaded = true;
    } else {
      return cachedModule.exports;
    }
  }

Это, с одной стороны, увеличивает производительность, а с другой, может создать некоторые проблемы, если мы не будем учитывать этот аспект. Например, определим файл greeting.js со следующим образом:

module.exports.name = "Alice";

В файле определена только одна строка, которая устанавливает свойство name.

Далее определим основной файл приложения - файл app.js:

const greeting1 = require("./greeting.js");
console.log(`Hello ${greeting1.name}`); //Hello Alice

const greeting2 = require("./greeting.js");
greeting2.name= "Bob";

console.log(`Hello ${greeting2.name}`);	//Hello Bob
// greeting1.name тоже изменилось
console.log(`Hello ${greeting1.name}`);	//Hello Bob

Несмотря на то, что здесь два раза получаем модуль с помощью функции require, но обе переменных - greeting1 и greeting2 будут указывать на один и тот же объект.

c:\app> node app.js
Hello Alice
Hello Bob
Hello Bob
c:\app> 

Структура модулей

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

  • Папка messages, которая содержит следующие файлы

    • index.js

    • morning.js

    • evening.js

  • Главный файл приложения app.js

  • В файл morning.js поместим следующую строку:

    module.exports = "Доброе утро";

    Аналогично изменим файл evening.js:

    module.exports = "Добрый вечер";

    Эти два файла определяют сообщения приветствия в зависимости от времени суток.

    И определим в файле index.js следующий код:

    const morning = require("./morning");
    const evening = require("./evening");
    
    module.exports = {
    	getMorningMessage : function(){ console.log(morning);},
    	getEveningMessage : function(){ console.log(evening);}
    }
    

    В модуле определен объект, который имеет две функции для вывода приветствий.

    Теперь используем этот модуль в файле app.js:

    const messages = require("./messages");
     
    messages.getMorningMessage();
    messages.getEveningMessage();
    

    Несмотря на то, что нет такого файла как "messages.js", но если в проекте есть каталог "messages", который содержит файл с именем index.js, то мы можем обращаться к модулю по имени каталога, как в данном случае.

    Запустим приложение, и на консоль будут выведены оба приветствия:

    c:\app> node app.js
    Доброе утро
    Добрый вечер
    c:\app> 
    
    Помощь сайту
    Юмани:
    410011174743222
    Перевод на карту
    Номер карты:
    4048415020898850