С модулями AMD, когда (или почему) можно использовать require() в define() ?

#requirejs #js-amd #curljs

#requirejs #js-amd #curljs

Вопрос:

Мое понимание модулей AMD (используя, например, RequireJS или curl.js ) является:

require() используется для асинхронной загрузки разных модулей, а при загрузке выполняется обратный вызов fn .

И для определения модуля у вас будут отдельные сценарии, которые используют define()

Но я видел, что некоторые модули используют require() внутри своего определения функции, например

 define([a, b, c], function(i, ii, iii){ 
    require([d, e, f], function(d, e, f) {
        // do some stuff with these require()'d dependancies
    })
    /* rest of the code for this module */ 
}) 
  

Но я нахожу это запутанным, потому что я бы подумал, что если модуль имеет зависимости, то они должны передаваться через основную define([dependancies], fnDefinition) функцию, а не внутри нее require() , как в приведенном выше примере.

Есть ли причина для этого?

Ответ №1:

Есть несколько причин, по которым вы можете захотеть использовать require() в модуле.

Но сначала убедитесь, что вы запрашиваете ссылку на правильную require переменную. В вашем примере ссылка на require является глобальной. Вам нужна ссылка на a require , ограниченная контекстом вашего модуля (иногда называемая «локальным требованием»).). Это просто:

 define(["a", "b", "c", "require"], function(i, ii, iii, require){ 
    require(["d", "e", "f"], function(moduleD, moduleE, moduleF) {
        // do some stuff with these require()'d dependencies
    })
    /* rest of the code for this module */ 
}); 
  

Основная причина, по которой это важно, — убедиться, что относительные идентификаторы модулей (например, «./peerModule» или «../ unclePath / cousinModule») разрешены правильно. (Это одна из причин, curl.js по умолчанию не имеет глобального require значения.)


Причины использования локального require :

  1. вы не знаете, какие модули необходимы во время сборки (или во время загрузки) из-за условий выполнения
  2. вы явно хотите отложить загрузку некоторых модулей до тех пор, пока они не понадобятся
  3. вы хотите загрузить вариант модуля на основе результатов обнаружения функций (хотя что-то вроде плагина dojo «has!» может быть лучшим решением (извините, ссылка ускользает от меня))

Наконец, AMD определяет второе использование require для совместимости с модулями, созданными в CommonJS Modules / 1.1, которые затем упаковываются в a define . Они выглядят так:

 define(function(require, exports, module){ 
    var a = require("pkgZ/moduleA"), // dependency
        b = require("pkgZ/moduleB"); // dependency
    /* rest of the code for this module */ 
}); 
  

Разработчики javascript на стороне сервера могут найти этот формат привлекательным. 🙂

Некоторые загрузчики AMD (такие как RequireJS 0.2 , dojo 1.7 , BDOAD и curl.js 0.6 ) обнаружит этот гибридный формат AMD / CJSM1.1 и найдет зависимости, сканируя модуль на require наличие вызовов.

Комментарии:

1. лучшая ссылка, которую я могу найти для has.js : mail.dojotoolkit.org/pipermail/dojo-contributors/2011-January/… Это не объясняет плагин, просто упоминает его.

2. если у кого-нибудь достаточно очков для создания тега curljs, я был бы признателен! 🙂

3. Итак, если у меня есть модуль, которому требуется определенная функциональность, недоступная во всех браузерах, я могу определить модуль как обычный, а затем внутри я могу выполнить условную проверку, а затем потребовать () соответствующие модули, которые заполняют недостающую функциональность, верно? И я предполагаю, что во время «сборки» я все равно мог бы минимизировать этот модуль с помощью моего сценария сборки, поэтому я не асинхронно загружаю неминифицированный сценарий модуля.

4. Правильно, это цель has! плагин. Цель состоит в том, чтобы создать карту строк UA * для профилей функций. Ваш сервер может либо выбрать настраиваемый файл из списка предварительно скомпилированных, объединенных файлов для строки UA текущего браузера, либо создать его точно в срок (и, надеюсь, кэшировать его для последующего использования). * Следует отметить, что не все «на борту» с повторным введением UA sniffing!

5. Справедливо ли это для первой точки входа «require», указанной после блока require.config() ? Я установил для enforceDefine значение true, которое помещает блок конфигурации внутрь define() , затем точка входа вызывается с использованием глобального «require» сразу после конфигурации.