Как я могу динамически загружать несколько оптимизированных модулей requirejs в рабочей среде?

Я начал играть с require js в фиктивном проекте. Теперь я хочу использовать скрипт r.js для создания своего проекта для производства.

Контекст таков:

  • Основной файл с именем start.js:

    require([/* some stuff */], function (){ /* app logic */ });
    

    у которого есть if, который решает, что мне нужно, исходя из некоторого условия.

  • Требуемые файлы: ModuleA или ModuleB.

  • И ModuleA, и ModuleB имеют зависимости.

    define([/*some deps*/], function(dep1, dep2...) { 
        /* app logic */ 
        return { /* interface */
    }
    
  • В режиме разработки все работает нормально, до оптимизации и конкатенации модулей.

  • При сборке с помощью r.js я указываю в качестве целевых модулей следующие: модули: [{имя: "start"}, {имя: "ModuleA"}, {имя: "ModuleB"}]

Проблема в том, что мой ModuleA становится:

 define(dep1 ..);
 define(dep2 ..);
 define(ModuleA ..);

Но ничего не загружается из ModuleA. Код из ModeulA в разработке загружается и выполняется, код после сборки загружается, но не запускается.

Как я могу решить эту проблему?

ОБНОВЛЕНИЕ

http://pastebin.com/p1xUcY0A --> start.js

http://pastebin.com/dXa6PtpX --> ModuleA js-animation.js

http://pastebin.com/xcCvhLrT --> ModuleB css-animation.js без отложений.

http://pastebin.com/j51V5kMt --> Файл конфигурации r.js, используемый при запуске оптимизатора.

http://pastebin.com/UVkWjwe9 --> Как выглядит js-animation.js после запуска r.js . Это файл, в котором есть проблемы. Я не получаю модуль js-анимации из этого файла. Требование не возвращает мой объект js-анимации.

Редактировать:

После удаления .js в конце определений модулей и из start js оптимизированным start.js будет http://pastebin.com/LfaLkJaT, а модуль js-анимации — http://pastebin.com/qwnpkCC6. В Chrome я получаю эту ошибку в своей консоли http://pastebin.com/Hq7HGcmm


person Vlad Nicula    schedule 07.08.2012    source источник
comment
Я могу вставить весь код фиктивного проекта, хотя в нем около 300 строк.   -  person Vlad Nicula    schedule 08.08.2012
comment
поместите свой код на pastebin.com и отредактируйте свой вопрос и прикрепите URL-адрес pastebin :)   -  person Andrei Sfat    schedule 09.08.2012
comment
не уверен, что pastebin - хороший вариант. Проекты имеют 4 файла js в разработке и должны иметь 3 в производстве. :|   -  person Vlad Nicula    schedule 09.08.2012
comment
Уточнение: есть ли у вашего стартового модуля логика за пределами require, которая генерирует массив зависимостей? И если да, то этот массив будет содержать имя зависимости ModuleA или ModuleB? Может быть, вы могли бы просто добавить код для start.js...   -  person rharper    schedule 11.08.2012
comment
Спасибо за комментарий @rharper. В моем модуле start.js есть два требования. Только один из двух внутренних вызовов require выполняется на основе условия. Это прояснило мою ситуацию?   -  person Vlad Nicula    schedule 14.08.2012
comment
@VladNicula Я думаю, было бы разумно опубликовать сжатую версию start.js. Включает ли /* some stuff */ в start.js модули A и/или B? Являются ли ваши требования внутри запуска синхронными или асинхронными?   -  person rharper    schedule 16.08.2012
comment
@rharper, спасибо, что предложили помощь. Я обновил вопрос со ссылками на pastebin.   -  person Vlad Nicula    schedule 17.08.2012


Ответы (2)


Я считаю, что проблема с вашей настройкой заключается в том, что вы заканчиваете имена зависимостей модулей на .js. Согласно документам:

RequireJS также по умолчанию предполагает, что все зависимости являются сценариями, поэтому он не ожидает увидеть завершающий суффикс «.js» в идентификаторах модулей. RequireJS автоматически добавит его при преобразовании идентификатора модуля в путь.

Если RequireJS видит имя модуля, оканчивающееся на .js, он предполагает, что имя модуля является путем относительно документа. Заканчивая имена зависимостей вашего модуля в .js, он отлично работает в режиме разработки, потому что RequireJS пойдет и загрузит файл, указанный как зависимость. В вашем случае он загрузит файл js/js-animation.js, увидит анонимный define и правильно загрузит модуль.

В производственной среде для вашего модуля start.js по-прежнему требуется "js/js-animation.js". RequireJS загрузит ваш оптимизированный модуль по пути js/js-animation.js, но теперь оптимизатор преобразовал ваши анонимные модули в именованные модули (в данном случае "js/js-animation"). В результате файл будет загружен, но ни один из define модулей в файле не имеет имени, совпадающего с "js/js-animation.js", так что в каком-то смысле ваш анимационный модуль отсутствует.

Решение / TL;DR: Удалите конечный .js из всех имен зависимостей модулей (и определений модулей в конфигурации r.js), и все будет в порядке. Таким образом, ваш start.js должен стать (изменения в строке 4):

require([], function () {
  var $html = $("html"),
    animationModule = localStorage['cssanimations'] == 'true' ? 
    'js/css-animation' : 'js/js-animation',
    $doc = $html.find("body");

  console.debug("loading ", animationModule);
  require([animationModule], function( animationModule ) {
    animationModule.run({
      target : $("div.flex")
    });
  } );
} );

Также обратите внимание, что вы можете использовать baseUrl и paths в конфигурации RequireJS для очистки имен модулей (например, чтобы вы могли удалить префикс js/).

person rharper    schedule 18.08.2012
comment
Привет, спасибо за подробный ответ. Я признателен за это. Я удалил .js из имен модулей, и теперь скрипт сборки объявляет модули без .js в конце их имен. Проблема все еще сохраняется. Второй производственный модуль, js-animation, по-прежнему имеет два определения, первый для плагина, второй для самого себя, и start js по-прежнему не может получить от него содержимое. :| - person Vlad Nicula; 22.08.2012
comment
@VladNicula Похоже, вы допустили ошибку при редактировании start.js. Вы удалили .js в конце имени вашего модуля (хорошо), но также удалили js/ спереди (которое вам нужно оставить). Ваш модуль require.js js-animation буквально называется 'js/js-animation', как видно из оптимизированного вывода. Я удивлен, если ваш код работал в режиме разработки с этой ошибкой... Добавьте js/ обратно к именам ваших модулей в start.js и попробуйте. - person rharper; 24.08.2012
comment
модуль start.js находится в папке js. Если я добавлю /js перед именами моих модулей, я получаю Uncaught Error: Script error, а в URL-адресе есть /js/js/module-name, что неверно... - person Vlad Nicula; 03.09.2012

Кажется, это проблема с текущей реализацией require.js. Обойти это можно было, создав глобальный посредник или модуль посредника, чтобы все динамически загружаемые модули вызывали посредника и объявляли о себе через событие. Это сработало для меня.

person Vlad Nicula    schedule 20.09.2012
comment
У меня такая же проблема, но с пакетами. Когда я пытаюсь загрузить уменьшенный пакет, мой main.js не выполняется - person chchrist; 19.02.2013