Несоответствующий анонимный модуль define ()

129

Я получаю эту ошибку , когда я просматриваю свой веб - приложение в первый раз ( как правило , в браузере с кэшем инвалидов).

Ошибка: несоответствующий анонимный модуль define (): function (require) {

HTML :

<html>
   .
   .
   .
   <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
   <script> var require = { urlArgs: "v=0.4.1.32" }; </script>
   <script data-main="assets/js/main" src="assets/js/libs/require.js"></script>
   <script src="assets/js/ace/ace.js?v=0.4.1.32"></script>
   </body>
</html>

JS :

$(function () {
    define(function (require) {
        // do something
    });
});

Кто-нибудь точно знает, что означает эта ошибка и почему она происходит?

исходный файл , краткое обсуждение этого на странице проблем github

Адонис К. Какулидис
источник

Ответы:

142

Как сказал AlienWebguy, в соответствии с документами, require.js может взорваться, если

  • У вас есть анонимное определение (« модули, которые вызывают define () без строкового идентификатора ») в собственном теге скрипта (я предполагаю, что на самом деле они означают где угодно в глобальной области)
  • У вас есть модули с конфликтующими именами
  • Вы используете плагины загрузчика или анонимные модули, но не используете оптимизатор require.js для их объединения.

У меня возникла эта проблема при включении пакетов, созданных с помощью browserify, вместе с модулями require.js. Решение было либо:

A. загрузите автономные пакеты non-require.js в теги скрипта до загрузки require.js или

Б. загрузить их с помощью require.js (вместо тега скрипта)

BT
источник
2
часто встречаются противоречивые имена
Хулио Маринс
1
Другое возможное решение, в некоторых особых случаях с анонимными модулями, - это перезапись функции requirejs.onError, чтобы предотвратить исключение ошибки по умолчанию, вызванное requirejs, которое останавливает выполнение последующих модулей или кода.
xtrm
1
Просто добавил запрос на перенос ( github.com/requirejs/requirejs/pull/1763 ), чтобы смягчить этот конкретный случай. Я думаю, что это очень распространенная проблема в наши дни.
Bob S
1
Спасибо, что сказал мне загрузить их раньше! Я не знаю, почему этого совета нет в документации по requirejs ... Вот здесь и пригодится стек
Тобиас Фейл,
14

У меня была эта ошибка, потому что я включил файл requirejs вместе с другими библиотеками, включенными непосредственно в тег скрипта. Эти библиотеки (например, lodash) использовали функцию определения, которая противоречила определению требования. Файл requirejs загружался асинхронно, поэтому я подозреваю, что определение require было определено после определения других библиотек, отсюда и конфликт.

Чтобы избавиться от ошибки, подключите все остальные файлы js с помощью requirejs.

eloone
источник
Оказалось, что многие библиотеки делают такие вещи или, по крайней мере, используют / экспортируют такую ​​функцию. Всем посоветую - если используют require - импортируйте все с require :)
Андрей Попов
12

Приступая к работе с reactjs, я столкнулся с проблемой, и, как новичок, документация могла быть написана на греческом языке.

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

анонимный определяет

define(function() {
        return { helloWorld: function() { console.log('hello world!') } };
 })


define(function() {
        return { helloWorld2: function() { console.log('hello world again!') } };
 })

определить со строковым идентификатором

define('moduleOne',function() {
    return { helloWorld: function() { console.log('hello world!') } };
})

 define('moduleTwo', function() {
      return { helloWorld2: function() { console.log('hello world again!') } };
})

Когда вы используете определение со строковым идентификатором, вы избежите этой ошибки, когда попытаетесь использовать такие модули:

require([ "moduleOne", "moduleTwo" ], function(moduleOne, moduleTwo) {
    moduleOne.helloWorld();
    moduleTwo.helloWorld2();
});
P.Brian.Mackey
источник
(Просто на заметку для потомков) У этого подхода есть некоторые недостатки, описанные в документации : «вызовы define (), включающие имя модуля… обычно генерируются инструментом оптимизации… сами nam [ing] modules… делают модули менее переносимы ... Обычно лучше избегать кодирования в имени модуля и просто позволить инструменту оптимизации записать имена модулей ». … А также в этой ветке GitHub . Похоже, это причина, по которой перечисление имени исключено в примерах для начинающих.
Марк Г.
10

Согласно документам :

Если вы вручную закодируете тег скрипта в HTML для загрузки скрипта с помощью анонимного вызова define (), может возникнуть эта ошибка.

Также это видно, если вы вручную кодируете тег скрипта в HTML для загрузки скрипта, который имеет несколько именованных модулей, но затем пытаетесь загрузить анонимный модуль, который в конечном итоге имеет то же имя, что и один из именованных модулей в скрипте, загруженном вручную закодированный тег скрипта.

Наконец, если вы используете плагины загрузчика или анонимные модули (модули, которые вызывают define () без строкового идентификатора), но не используете оптимизатор RequireJS для объединения файлов, эта ошибка может возникнуть. Оптимизатор знает, как правильно называть анонимные модули, чтобы их можно было объединить с другими модулями в оптимизированном файле.

Чтобы избежать ошибки:

  • Обязательно загрузите все скрипты, которые вызывают define () через RequireJS API. Не следует вручную кодировать теги сценариев в HTML для загрузки сценариев, содержащих вызовы define ().

  • Если вы вручную кодируете тег сценария HTML, убедитесь, что он включает только именованные модули и что анонимный модуль, который будет иметь то же имя, что и один из модулей в этом файле, не загружен.

  • Если проблема заключается в использовании плагинов-загрузчиков или анонимных модулей, но оптимизатор RequireJS не используется для объединения файлов, используйте оптимизатор RequireJS.

AlienWebguy
источник
3
Это анонимно определенный модуль? github.com/requirejs/example-multipage/blob/master/www/js/app/…
уличный фонарь
5

Имейте в виду, что некоторые расширения браузера могут добавлять код на страницы. В моем случае у меня был плагин «Emmet in all textareas», который испортил мои requireJs. Убедитесь, что в ваш документ не добавлен дополнительный код, проверив его в браузере.

Вектор
источник
5

Существующие ответы хорошо объясняют проблему, но если включение ваших файлов сценариев с использованием или до использования requireJS не является легким вариантом из-за устаревшего кода, слегка взломанный обходной путь - удалить require из области окна перед тегом сценария, а затем восстановить его после слов. В нашем проекте это скрыто за вызовом серверной функции, но на самом деле браузер видит следующее:

    <script>
        window.__define = window.define;
        window.__require = window.require;
        window.define = undefined;
        window.require = undefined;
    </script>
    <script src="your-script-file.js"></script>        
    <script>
        window.define = window.__define;
        window.require = window.__require;
        window.__define = undefined;
        window.__require = undefined;
    </script>

Не самый аккуратный, но, похоже, работает и сэкономил много рефрактора.

jcbdrn
источник
5
На самом деле никогда этого не делай. Он не работает в IE.
jcbdrn
2
Периодически в IE сценарии, включенные в requireJS, могли бы определить пропущенные из области их окна, даже если команда require поступала после восстановления этих переменных. Нам так и не удалось выяснить, почему это произошло, поэтому мы отказались от этого хакерского решения.
jcbdrn
2
@jcbdrn Это не только в IE. Я видел, как это происходило на другой платформе. Причина в том, что спецификация HTML действительно предлагает гарантии в отношении порядка выполнения синхронных скриптов, но только относительно других синхронных скриптов . Это не гарантирует выполнение асинхронных скриптов относительно синхронного (или наоборот). Итак, в коде, показанном в ответе здесь, возможно выполнение асинхронного сценария между любыми двумя scriptэлементами.
Луи
Если у вас есть возможность редактировать пакет js, который вы импортируете, вы можете просто обернуть все это так:(function(){ var define = undefined; // the UMD registration code won't find the global 'define' anymore! // generated content goes here })()
Пит Торн,
2

Или вы можете использовать этот подход.

  • Добавьте require.js в свою базу кода
  • затем загрузите свой скрипт через этот код

<script data-main="js/app.js" src="js/require.js"></script>

Что он будет делать, он загрузит ваш скрипт после загрузки require.js .

Умар Асгар
источник