Невідповідний анонімний модуль define ()


129

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

Помилка: невідповідний анонімний модуль define (): функція (вимагає) {

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, згідно з документами, вимога.js може підірватись, якщо

  • У вас є анонімне визначення (" модулі, які викликають define () без ідентифікатора рядка ") у своєму власному тезі сценарію (я припускаю, що вони фактично означають будь-де в глобальному масштабі)
  • У вас є модулі, які мають суперечливі імена
  • Ви використовуєте плагіни завантажувача або анонімні модулі, але не використовуєте оптимізатор Requ.js для їх поєднання

У мене виникла ця проблема, включаючи пакети, побудовані за допомогою перегляду разом з модулями Requ.js. Рішення полягало в тому, щоб:

A. завантажте автономні пакети non-Require.js в теги сценарію до завантаження Requ.js або

B. завантажте їх за допомогою Requ.js (замість тегу сценарію)


2
суперечливі імена є загальним
Хуліо Марінс

1
Іншим можливим рішенням, у деяких спеціальних випадках з анонімними модулями, є перезапис функції Requjs.onError, щоб запобігти виключенню помилки за замовчуванням, викинутого Requjs, який зупиняє виконання послідовних модулів або коду.
xtrm

1
Просто додав запит на витяг ( github.com/requirejs/requirejs/pull/1763 ), щоб полегшити цей випадок. Я думаю, що це дуже поширена проблема в наші дні.
Bob S

1
Дякуємо за те, що ви мені сказали завантажувати їх раніше! Я не знаю, чому ця порада не є у власній документації Requjs ... Ось тут і стак корисний
Tobias Feil

14

У мене виникла помилка, оскільки я включив файл Requjs разом з іншими бібліотеками, включеними безпосередньо в тег сценарію. Ці бібліотеки (наприклад, lodash) використовували функцію визначення, яка суперечила визначенню Require. Файл Requjs завантажувався асинхронно, тому я підозрюю, що визначення вимоги було визначене після визначення інших бібліотек, отже, конфлікт.

Щоб позбутися від помилки, включіть усі інші js-файли, використовуючи Requjs.


Виявилося, що багато бібліотек роблять таку дію або принаймні використовують / експортують таку функцію. Я пораджу всім - якщо вони використовують вимагають - імпортуйте все з попитом :)
Андрій Попов

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();
});

(Зауваження для нащадків) Там є деякі недоліки цього підходу, описані в документації : «визначають () виклики , які включають в себе ім'я для модуля ... зазвичай генерується оптимізація інструменту ... Нама [ я ] модулі самі ... робить модулі менш портативні… Зазвичай найкраще уникати кодування імені для модуля, а просто дозволити інструменту оптимізації записати в назви модуля. " … А також у цій темі GitHub . Це, мабуть, є причиною того, що в прикладах для початківців виключено перелік імені.
Марк Г.

10

Згідно документації :

Якщо ви вручну кодуєте тег сценарію в HTML для завантаження сценарію з анонімним викликом define (), ця помилка може статися.

Також можна побачити, якщо ви вручну кодуєте тег скрипту в HTML, щоб завантажити сценарій, який має кілька названих модулів, але потім спробуйте завантажити анонімний модуль, який в кінцевому підсумку має те саме ім'я, що й один із названих модулів у скрипті, завантаженому вручну закодований тег сценарію.

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

Щоб уникнути помилки:

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

  • Якщо ви вручну кодуєте тег HTML-скрипту, переконайтеся, що він містить лише названі модулі, а анонімний модуль, який матиме те саме ім'я, що і один із модулів у цьому файлі, не завантажений.

  • Якщо проблема полягає у використанні плагінів завантажувача або анонімних модулів, але оптимізатор RequireJS не використовується для пакетування файлів, використовуйте оптимізатор RequireJS.


3
Це анонімно визначений модуль? github.com/requirejs/example-multipage/blob/master/www/js/app/…
вуличне

5

Майте на увазі, що деякі розширення браузера можуть додавати код на сторінки. У моєму випадку у мене був плагін "Emmet у всіх текстах", який переплутався з моїми вимогами. Переконайтесь, що до документа не додано жодного додаткового коду, переглянувши його у веб-переглядачі.


5

Існуючі відповіді добре пояснюють проблему, але якщо включення файлів скриптів із використанням або раніше вимагаєJS - це не простий варіант, завдяки застарілому коду злегка хиткий спосіб вирішити проблему - видалити вимогу з області вікна перед тегом сценарію, а потім відновити після неї. У нашому проекті це обговорюється за функцією виклику на стороні сервера, але фактично браузер бачить наступне:

    <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>

Не найновіший, але, здається, працює і врятував багато рефракторів.


5
Насправді ніколи цього не роби. Він не працює належним чином в IE.
jcbdrn

2
Переривчасті в IE скрипти, що входять до RequJS, мали б визначити пропущені в їхньому вікні області, навіть коли команда вимагала після відновлення цих змінних. Нам ніколи не вдалося з'ясувати, чому це сталося, тому ми відмовилися від цього хакітського рішення.
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 .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.