На сегодняшний день одна из наиболее часто используемых библиотек JavaScript — это RequireJS. В каждом проекте, в котором я участвовал в последнее время, мы используем RequireJS или я предлагаю добавить RequireJS. В этом посте я собираюсь описать, что такое RequireJS и некоторые его основные сценарии.
Определения асинхронных модулей (AMD)
Вы не можете начать говорить о RequireJS, не упомянув, что такое модули JavaScript и что такое AMD.
Модули JavaScript — это просто фрагменты кода, которые следуют SRP (принципу единой ответственности) и предоставляют общедоступный API. В сегодняшней разработке JavaScript вы инкапсулируете множество функций внутри модулей, и в большинстве проектов каждый модуль существует в своем собственном файле. Это делает жизнь разработчиков JavaScript немного сложнее, поскольку им необходимо постоянно следить за зависимостями между модулями и загружать модули в определенном порядке, иначе возникнут ошибки во время выполнения.
Когда вы хотите загрузить модули JavaScript, вы используете теги script. Чтобы загрузить зависимости модуля, сначала нужно загрузить зависимость, а затем зависимую. При использовании тегов сценариев необходимо организовать их загрузку в определенном порядке, и сценарии будут загружаться синхронно. Вы можете использовать ключевые слова async и defer, чтобы сделать загрузку асинхронной, но вы можете потерять порядок загрузки в процессе. Другим вариантом является объединение всех сценариев, но все же вам нужно будет упорядочить их в правильном порядке во время объединения.
AMD занимается определением модулей таким образом, чтобы модуль и его зависимости могли загружаться асинхронно и в правильном порядке.
CommonJS , который является попыткой стандартизировать общие шаблоны JavaScript, включает определение AMD, которое я рекомендую вам прочитать, прежде чем вы приступите к этой статье. В ECMAScript 6, спецификации JavaScript vNext, есть спецификации для экспорта, импорта и модулей, которые станут частью языка JavaScript, но только в ближайшем будущем. Именно здесь RequireJS входит в нашу историю.
RequireJS?
RequireJS — это инфраструктура файлов и модулей JavaScript, которую можно загрузить с http : //requirejs.org / или с помощью Nuget, если вы работаете в среде Visual Studio. Он поддерживается как в браузерах и в серверных средах , таких как Node.js . Используя RequireJS, вы будете загружать только соответствующие зависимости модуля в правильном порядке.
Когда вы используете его, то RequireJS создает теги сценариев для каждой определенной вами зависимости и загружает их на лету с помощью функции head.appendChild () . Затем, после загрузки зависимостей, RequireJS определит правильный порядок определения модулей и вызовет определение каждого модуля в этом правильном порядке. Это означает, что вам нужен только один root для загрузки всей необходимой вам функциональности, а RequireJS сделает все остальное. Чтобы использовать эту функциональность, вам нужно определить каждый из ваших модулей с помощью API RequireJS, иначе ничего не будет работать, как ожидалось.
RequireJS API существует внутри пространства имен requirejs, которое загружается при загрузке скрипта RequireJS. RequireJS включает в себя три основные функции API:
- define — функция используется для определения модуля. Каждый модуль определен с уникальным идентификатором модуля, который будет использоваться функциональностью во время выполнения RequireJS. Функция define — это глобальная функция, и вам не нужно использовать ее с пространством имен requirejs .
- require — функция используется для загрузки требуемых зависимостей. Это глобальная функция, и вам не нужно использовать ее с пространством имен requirejs .
- config — функция используется для настройки функциональности времени выполнения requirejs .
Позже мы рассмотрим, как использовать эти функции, но сначала давайте разберемся, как запустить процесс загрузки RequireJS.
Атрибут основной данные
После того, как вы загрузили RequireJS, первое, что нужно сделать после того, как вы поместите его скрипт в свое решение, это понять, как RequireJS начинает работать. После загрузки RequireJS выполняется поиск сценария с атрибутом data-main (это должен быть тот же сценарий с атрибутом src, установленным для загрузки RequireJS). Для data-main должна быть установлена базовая ссылка для всех сценариев. Из базового URL-адреса RequireJS начнет загрузку всех соответствующих модулей. Вот пример тега script с атрибутом data-main :
<script data-main="scripts/app.js" src="scripts/require.js"></script>
Другой способ определить базовый URL-адрес — использовать функцию config, которую мы увидим позже. RequireJS предполагает, что все зависимости являются сценариями, поэтому при объявлении зависимости вам не нужно использовать суффикс .js.
Функция конфигурации
Если вы хотите изменить значения конфигурации RequireJS по умолчанию на ваши собственные конфигурации, вы можете сделать это с помощью функции requirejs.config . Функция config получает объект параметров, который может включать в себя множество параметров конфигурации. Вот некоторые из конфигураций, которые вы можете использовать:
- baseUrl — корневой путь для запуска загрузки модулей.
- пути — отображение пути для модулей, которые не существуют в рамках baseUrl
- shims — конфигурация для зависимостей, экспорт и функция инициализации, чтобы обернуть скрипты / модули, которые не используют функцию определения RequireJS . Например, если библиотека подчеркивания не использует определяющую функцию RequireJS, и вы все еще хотите использовать ее с RequireJS, вам придется определить ее как прокладку в функции конфигурации .
- deps — массив зависимостей для загрузки.
Вот пример использования функции config :
require.config({ //By default load any module IDs from scripts/app baseUrl: 'scripts/app', //except, if the module ID starts with "lib" paths: { lib: '../lib' }, // load backbone as a shim shim: { 'backbone': { //The underscore script dependency should be loaded before loading backbone.js deps: ['underscore'], // use the global 'Backbone' as the module name. exports: 'Backbone' } } });
В качестве базового URL-адреса в этом примере указано scripts / app, каждый модуль, который начинается с lib, настроен для использования из папки scripts / lib, а магистральный канал загружен в качестве прокладки с зависимостями.
Определение модулей с помощью RequireJS
Модули — это просто объекты с хорошей областью видимости, которые предоставляют API и инкапсулируют свои внутренние компоненты. Чтобы определить модуль, RequireJS предоставляет функцию define . В каждом файле JavaScript должен быть только один вызов define для соглашения. Функция define получает массив зависимостей и функцию, которая будет содержать все определения модуля. По соглашениям функция определения модуля получает в качестве параметров все предыдущие зависимости и в порядке их поступления в массив. Например, вот простое определение модуля:
define(["logger"], function(logger) { return { firstName: “John", lastName: “Black“, sayHello: function () { logger.log(‘hello’); } } } );
Как видите, массив передается в функцию define с зависимостью от логгера, которая позже используется в модуле. Также вы можете видеть, что в функции определения модуля есть параметр, называемый logger, который будет установлен для загруженного модуля logger. Каждый модуль должен возвращать свой API, который в этом случае имеет два свойства (firstName и lastName) и функцию (sayHello). Позже, если вы загрузите этот модуль как другую зависимость модуля с идентификатором модуля, вы сможете использовать предоставляемый API.
Использование требуемой функции
Еще одна полезная функция в RequireJS — это функция require . Функция require используется для загрузки зависимостей без создания модуля. Например, здесь используется функция require, которая определяет функцию, для работы которой требуется jQuery:
require(['jquery'], function ($) { //jQuery was loaded and can be used now });
Резюме
В этой статье я представил RequireJS, которая является одной из библиотек, которые я использую в каждом проекте приложения JavaScript. Кроме простой загрузки зависимостей модуля и в соответствующем порядке, RequireJS помогает писать модульный код JavaScript, который гораздо более удобен в обслуживании и может использоваться повторно.