Трудно представить себе времена до NodeJS, но еще более темные времена были до CommonJS. Не совсем уверены, что такое CommonJS? Ну что, начнем с середины?

CommonJS был запущен инженером Mozilla Кевином Дангуром в январе 2009 года для решения проблемы отсутствия общепринятых методов модульности в программировании на Javascript. Как они этого добились?

«Группа CommonJS определила формат модуля для решения проблем с областью действия JavaScript, убедившись, что каждый модуль выполняется в своем пространстве имен. Это достигается за счет принуждения модулей к явному экспорту тех переменных, которые они хотят предоставить «вселенной», а также путем определения других модулей, необходимых для правильной работы».
— Документы Webpack

Почему модульность? У модульности есть четыре существенных преимущества. Во-первых, это возможность повторного использования. Модули позволяют импортировать код и использовать его в других модулях, или несколько модулей можно экспортировать в пакет и устанавливать в разных средах. Далее, модули предоставляют нам компонуемость, потому что код можно явно определить и быстро удалить. Работа в модулях изолирует разделы методов, поэтому работу можно создавать (а затем исправлять) отдельно. Несколько разработчиков могут работать над изолированными модулями независимо друг от друга и избегать конфликтов слияния. Наконец, модульность обеспечивает организацию программы за счет естественных точек разделения. Написание большого количества кода и переменных менее подвержено ошибкам благодаря модульности, поскольку она не загрязняет глобальное пространство имен и позволяет избежать коллизий.

Давным-давно, до модульности, если разработчики хотели сделать код из других файлов доступными друг для друга, они обращались к переменным и функциям из глобального объекта окна. Затем, чтобы скомпилировать весь код в браузере, каждый файл включается с тегами script в файл index.html. Эта система не очень многоразовая, и большая часть программы находится в той же области. Но должен был быть лучший способ.

Появились немедленно вызываемые функциональные выражения. IIFE — это анонимные функции, заключенные в круглые скобки. Затем, как и для любой другой функции, для ее вызова мы добавляем еще одну пару круглых скобок в ее конец. IIFE значительно очищает глобальное пространство имен, но теги script по-прежнему необходимы. Там должен быть лучший способ!

Наконец, у нас есть CommonJS. CommonJS делает каждый файл своим модулем. Затем каждый файл явно определяет импорт (или зависимости) и явный экспорт, которые будут доступны для любого другого файла. Взгляните на явно определенный экспорт ниже.

// customers.js
var customers = ["Rachel", "Galen", "Charles"]
  
module.exports = {   
  getCustomers: function () {     
    return users   
  },   
  sortCustomers: function () {     
    return users.sort()   
  },   
  firstCustomer: function () {     
    return users[0]   
  } 
}

Для простоты любая информация о модуле может быть помещена в объект. Затем все, что мы хотим экспортировать из модуля, мы можем прикрепить к module.exports! Теперь посмотрим, как мы можем импортировать.

// acounting.js
const customers = require('./users')  
customers.getCustomers() // ["Rachel", "Galen", "Charles"] 
customers.sortCustomers() // ["Charles", "Galen", "Rachel"] 
customers.firsCustomer() // ["Charles"]

Если вы раньше использовали Node, вы узнаете стандарт CommonJS. Node использует вариант этой спецификации. Однако, в отличие от Node, браузеры естественным образом не поддерживают CommonJS. Другим недостатком является то, что CommonJS загружает свои модули синхронно. Ба! Все эти преимущества и еще две проблемы. Мы можем исправить это с помощью сборщиков модулей, таких как Webpack. Если мы игнорируем сложность, сборщик модулей, по сути, превращает ваш код из нескольких файлов в один.

payroll.js ------> |         |
customers.js ----> | Bundler | -> bundle.js
accounting.js ---> |         |

После того, как все файлы объединены в один, что тогда? Как они это делают? Ну, с одним большим IIFE!

В заключение, модули CJS представляют собой повторно используемый код, доступный для зависимых файлов. Он достигает всех наших целей организованного управления зависимостями, разделения задач, изоляции и компонуемости. Хотя с 2009 года многое изменилось, CommonJS проложил путь к современным методам модульности, которые являются требованием любой программы, написанной сегодня.