不匹配的匿名define()模块


129

首次浏览Web应用程序时(通常是在禁用缓存的浏览器中),我遇到此错误。

错误:匿名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问题页面上对此文件进行简短讨论

Answers:


142

就像AlienWebguy说,每文档,require.js可以炸毁如果

  • 您在其自己的脚本标签中有一个匿名的define(“ 调用define()且没有字符串ID的模块 ”))(我假设它们实际上意味着全局范围内的任何地方)
  • 您的模块名称冲突
  • 您使用加载程序插件或匿名模块,但不使用require.js的优化程序将它们捆绑在一起

在包含用browserify构建的捆绑包以及require.js模块时遇到了这个问题。解决方案是:

A.在加载require.js 之前,将非require.js独立捆绑软件加载到脚本标记中,或者

B.使用require.js(而不是脚本标签)加载它们


2
相互冲突的名字很常见
Julio Marins

1
在某些特殊情况下使用匿名模块的情况下,另一种可能的解决方案是覆盖requirejs.onError函数,以防止requirejs抛出默认错误异常,该异常会停止成功执行模块或代码。
xtrm

1
刚刚添加了一个拉取请求(github.com/requirejs/requirejs/pull/1763)来放松这种确切的情况。我认为这是一个非常普遍的问题。
鲍勃·S

1
感谢您告诉我之前加载它们!我不知道为什么这个技巧不在requirejs自己的文档中……那是堆栈派上用场的地方
Tobias Feil

14

我遇到此错误是因为我将requirejs文件以及其他包含在脚本标记中的库直接包含在内。这些库(例如lodash)使用了一个与require的定义冲突的define函数。requirejs文件正在异步加载,因此我怀疑在其他库定义之后定义了require的定义,因此发生了冲突。

要消除该错误,请使用requirejs包含所有其他js文件。


事实证明,很多库都这样做,或者至少使用/导出了这样的功能。我会劝告所有人-如果他们使用require-请使用require导入所有内容:)
Andrey Popov 2015年

12

在开始使用reactjs时,我遇到了这个问题,作为初学者,文档也可能是用希腊语编写的。

我遇到的问题是,当您应该使用“字符串ID”时,大多数初学者示例都使用“匿名定义”。

匿名定义

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


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

用字符串ID定义

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

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

当您使用带字符串ID的define时,当您尝试像这样使用模块时,您将避免此错误:

require([ "moduleOne", "moduleTwo" ], function(moduleOne, moduleTwo) {
    moduleOne.helloWorld();
    moduleTwo.helloWorld2();
});

(只是给后人一个注释)一些缺点这种方法,描述在文档:“定义()调用,包括该模块的名称...通常由优化工具......南产生[和]模块自己......使模块的移植性较低……通常最好避免在模块名称中编码,而让优化工具在模块名称中刻录。” …以及该GitHub线程中。这似乎是在初学者示例中排除列出名称的原因。
Mark G.

10

根据文档

如果您手动编写HTML脚本标记以通过匿名define()调用加载脚本,则可能会发生此错误。

还可以看到,如果您手动以HTML编写脚本标记以加载具有一些命名模块的脚本,然后尝试加载匿名模块,该模块最终与手动加载的脚本中的命名模块之一具有相同的名称编码脚本标签。

最后,如果您使用加载程序插件或匿名模块(调用无字符串ID的define()的模块)但不使用RequireJS优化器将文件组合在一起,则可能会发生此错误。优化器知道如何正确命名匿名模块,以便它们可以与优化模块中的其他模块组合。

为避免该错误:

  • 确保通过RequireJS API加载所有调用define()的脚本。不要手动在HTML中编写脚本标记,以加载其中具有define()调用的脚本。

  • 如果您手动编码HTML脚本标记,请确保它仅包含命名模块,并且不会加载与该文件中的模块名称相同的匿名模块。

  • 如果问题是使用加载程序插件或匿名模块,但RequireJS优化器未用于文件捆绑,请使用RequireJS优化器。



5

请注意,某些浏览器扩展可以向页面添加代码。在我的情况下,我有一个“在所有textareas中的Emet”插件,与我的requireJs搞混了。通过在浏览器中检查文档,确保没有多余的代码被添加到您的文档中。


5

现有的答案很好地说明了问题,但是如果由于遗留代码而使用requireJS或在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>

并非最整洁,但似乎可以工作,并且节省了大量折光费。


5
实际上从来没有这样做。在IE中无法正常运行。
jcbdrn 2015年

2
在IE中,requireJS随附的脚本会断断续续地定义其窗口范围内的缺失内容,即使在还原这些变量之后发出了require命令。我们从未设法弄清楚为什么会发生这种情况,因此我们放弃了这种骇人听闻的解决方案。
jcbdrn '16

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 })()
Pete Thorne

2

或者您可以使用这种方法。

  • 在代码库中添加require.js
  • 然后通过该代码加载脚本

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

它将执行的操作将在加载require.js之后加载您的脚本

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.