Поскольку мы используем Node.js в качестве повседневной работы. Вы знаете, как работает модульная система? Прежде чем мы углубимся в нашу историю, я хочу уделить немного времени объяснению модулясамого.

Что такое модуль?

модуль подобен строительному блоку. Программный небоскреб состоит из строительных блоков.

Когда мы используем стороннюю библиотеку в качестве нашей зависимости. Мы импортируем эту библиотеку в наш проект как модуль. На самом деле мы используем методы или объекты из этой библиотеки.

Чтобы быть более общим:

Модуль — это целое, инкапсулированное объектом или методом.

Например:

Когда мы хотим прочитать файл в main.js , мы напишем следующий код:

// Import the fs object
const fs = require('fs');
// Using the readFileSync method of fs object.
fs.readFileSync('./fileName.json');

Что такое модуль на самом деле?

Модуль — это файл

Удивляться такому выводу?! Я не хотел объяснять вещи сложно и волшебно. Мне нравятся простые идеи. Простые идеи всегда оказывают на нас сильное влияние.

Любой модуль был написан человеком и с исходным кодом в текстовом формате. Даже это сделано искусственным интеллектом или автоматически создано другой программой. Источником истины стал человеческий разум.

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

Зачем нужны модули?

Большинство из нас просто используют модули каждый день. Возможно, вы уже признали в своем сердце, что мы должны использовать модуль. И не зная, почему и как работает модуль, это не имеет большого значения для разработки вашей программы.

Но когда вам понадобится устранить неполадки в вашей программе, вы будете благодарны мне. 🤓

На самом деле компьютеру НЕ вообще не нужны модули.

С самого начала мы писали нашу программу в одном файле записи. В этом подходе нет ничего страшного. Мир наполнен миром и любовью. Но вдруг в один прекрасный день автор программы покинул компанию. Боссу нужен новый программист для поддержки программы.

Что за чертовщина с этим единственным огромным входным файлом!!!

Когда программу необходимо поддерживать, возникает проблема:

  • Разные люди изменяют один и тот же файл. Вызывает множество конфликтов
  • Для безопасности программы. Некоторые методы или объекты не должны быть доступны другим.
  • Код очень запутан для чтения.
  • Сложно отлаживать.

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

  • Легче разделить разные модули в виде отдельных файлов для каждого человека. Меньше конфликтов.
  • Более легко защитить частные методы или объекты в собственном модуле.
  • Легко для человечества, чтобы прочитать программу. Потому что мы можем организовать программу с какой-то логикой.
  • Его также сложно отлаживать, но это может немного ослабить давление, связанное с тем, что мы можем сосредоточиться на одном из важных модулей.

Как работает модульная система в Nodejs?

Обычный способ импорта модуля — использование функции require. Давайте продемонстрируем модульную систему на примере:

Вопрос. Реализуйте модуль cache, включая метод get и метод set для управления хранилищем key:value.

Здесь нам нужны 2 файла: index.js и cache.js :

cache 
├── cache.js 
└── index.js
  • cache.js реализация:
/**
 * cache/cache.js
 */
class Cache {
  constructor() {
    this.cache = {};
  }
  get(key) {
    return this.cache[key];
  }
  set(key, value) {
    return (this.cache[key] = value);
  }
}
module.exports = new Cache(); // Export a Cache object.
  • index.js реализация:
/**
 * cache/index.js
 */
const cache = require('./cache'); // Import the Cache object
cache.set('name', 'Herb');
console.log(cache.get('name')); // Herb

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

  • Откуда module?
  • Откуда require?
  • Зачем нам нужен module.exports для экспорта объекта, который мы хотим?
  • Если я require один и тот же модуль несколько раз, будут ли эти объекты одним и тем же?
  • Почему require('./cache') может найти файл cache.js, не используя точно такое же имя файла?

Камера вниз… Здесь так много вопросов. Честно говоря, я был очень сбит с толку, когда писал свою первую программу Nodejs о require и module. Я просто использую его каждый день, не зная, как он работает. И я всегда путаю module.exports и modules.export……

Вот официальный документ Nodejs о модульной системе.

TLTR: module и require – это параметры функции-оболочки, которая заключает в себе весь код модуля.

(function(exports, require, module, __filename, __dirname) {
// Здесь фактически находится код модуля
});

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

Как мы знаем до сих пор, нам нужны require и module в качестве параметра. Кроме того, модуль является объектом и имеет свойство с именем exports. Чтобы найти модуль, каждый модуль должен иметь свойство id для идентификации самого себя.

Итак, давайте создадим новый файл с именем module.js и поместим код cache.js в функцию-оболочку function cache(module, require):

/**
 * module.js
 */
class Module {
  constructor(id, exports = {}) {
    this.id = id;
    this.exports = exports;
  }
}
function cache(module, require) {
  /**
   * cache/cache.js
   */
  class Cache {
    constructor() {
      this.cache = {};
    }
    get(key) {
      return this.cache[key];
    }
    set(key, value) {
      return (this.cache[key] = value);
    }
  }
  module.exports = new Cache();
}

Теперь у нас есть код cache.js, обернутый функцией-оболочкой. Тогда как мы можем экспортировать наш new Cache()?

Выполнить функцию-оболочку cache!

const cacheModule = new Module('./cache')
cache(cacheModule);
console.log(cacheModule); // Module { id: 'cache.js', exports: Cache { cache: {} } }

Теперь мы сами создали наш cacheModule. Заметь:

  • cacheModule.exports содержат наш объект, который необходимо экспортировать.
  • Мы используем ./cache в качестве идентификатора нашего модуля. Тогда мы можем обратиться к этому модулю по ./cache.

Затем нам нужно центральное место для хранения наших модулей:

const modules = {
  './cache': cacheModule,
};

Следующим шагом нам нужно импортировать cacheModule.expots в index.js с помощью функции require. Вот простая реализация функцииrequire:

const __require__ = (id) => modules[id].exports; // avoid with nodejs native require function.

Затем мы можем обернуть наш код index.js и выполнить его!

function index(module, require) {
  /**
   * cache/index.js
   */
  const cache = require('./cache'); 
  cache.set('name', 'Herb');
  console.log(cache.get('name'));
}
const indexModule = new Module('./index');
index(indexModule, __require__); // Herb

Когда вы запустите node modules.js , вы увидите, что код index.js был успешно выполнен.