不一致の匿名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の問題のページでのソースファイルに関する短いディスカッション

回答:


142

AlienWebguyが言ったように、ドキュメントによれば、require.jsは爆発する可能性があります

  • 独自のスクリプトタグ内に匿名の定義(「文字列IDなしでdefine()を呼び出すモジュール」)があります(実際、これらはグローバルスコープのどこかを意味していると思います)
  • 名前が競合するモジュールがあります
  • ローダープラグインまたは匿名モジュールを使用するが、require.jsのオプティマイザーを使用してそれらをバンドルしない

require.jsモジュールとともにbrowserifyでビルドされたバンドルを含めるときに、この問題が発生しました。解決策は:

A. require.jsがロードされる前に、スクリプトタグでnon-require.jsスタンドアロンバンドルをロードする、または

B.(スクリプトタグの代わりに)require.jsを使用してそれらをロードする


2
名前の競合はよくあることです
Julio Marins、

1
匿名モジュールの一部の特殊なケースでの別の可能な解決策は、requirejs.onError関数を上書きして、requirejsによってスローされるデフォルトのエラー例外が発生しないようにして、連続するモジュールまたはコードの実行を停止することです。
xtrm

1
その正確なケースを緩和するために、プルリクエスト(github.com/requirejs/requirejs/pull/1763)を追加しました。最近はよくある問題だと思います。
Bob S

1
以前にロードするように言ってくれてありがとう!なぜこのヒントがrequirejsの独自のドキュメントに含まれていないのかわかりません...スタックが役立つのはここです
Tobias Feil

14

requirejsファイルとスクリプトタグに直接含まれている他のライブラリを一緒に含めたため、このエラーが発生しました。これらのライブラリ(lodashなど)は、requireの定義と競合する定義関数を使用していました。requirejsファイルは非同期で読み込まれていたため、requireの定義が他のライブラリの定義の後に定義されたため、競合が発生したと考えられます。

エラーを取り除くには、requirejsを使用して他のすべてのjsファイルを含めます。


多くのライブラリがそのようなことをするか、少なくともそのような関数を使用/エクスポートすることが判明しました。私は皆に助言します-彼らがrequireを使用する場合-requireですべてをインポートします:)
Andrey Popov

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で定義を使用すると、次のようにモジュールを使用するときにこのエラーを回避できます。

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

(後世のためのメモ)このアプローチには、ドキュメントに記載されているいくつかの欠点があります。「モジュールの名前を含むdefine()呼び出しは、通常、最適化ツールによって生成されます...モジュールを自分で名前付け...モジュールの移植性が低い...通常は、モジュールの名前をコーディングせずに、最適化ツールにモジュール名を焼き込ませるのが最善です。」… このGitHubスレッドも同様です。これが、初心者の例で名前のリストが除外されている理由のようです。
マークG.17年

10

ドキュメントごと:

HTMLでスクリプトタグを手動でコーディングして、匿名のdefine()呼び出しでスクリプトをロードすると、このエラーが発生する可能性があります。

また、HTMLでスクリプトタグを手動でコーディングして、いくつかの名前付きモジュールを持つスクリプトをロードし、その後、手動でロードされたスクリプト内の名前付きモジュールの1つと同じ名前を持つ匿名モジュールをロードしようとした場合にも見られますコード化されたスクリプトタグ。

最後に、ローダープラグインまたは匿名モジュール(文字列IDなしでdefine()を呼び出すモジュール)を使用するが、RequireJSオプティマイザーを使用してファイルを結合しない場合、このエラーが発生する可能性があります。オプティマイザは、匿名モジュールを正しく命名する方法を知っているため、最適化されたファイル内で他のモジュールと組み合わせることができます。

エラーを回避するには:

  • 必ずRequireJS APIを介してdefine()を呼び出すすべてのスクリプトをロードしてください。HTMLのスクリプトタグを手動でコーディングして、define()呼び出しを含むスクリプトをロードしないでください。

  • HTMLスクリプトタグを手動でコーディングする場合は、名前付きモジュールのみが含まれていることと、そのファイル内のモジュールの1つと同じ名前を持つ匿名モジュールが読み込まれていないことを確認してください。

  • ローダープラグインまたは匿名モジュールの使用に問題があるが、ファイルのバンドルにRequireJSオプティマイザーが使用されていない場合は、RequireJSオプティマイザーを使用します。


3
これは匿名で定義されたモジュールですか? github.com/requirejs/example-multipage/blob/master/www/js/app/…–
街灯

5

一部のブラウザ拡張機能では、ページにコードを追加できることに注意してください。私の場合、「すべてのテキスト領域のエメット」プラグインがあり、requireJがめちゃくちゃになりました。ブラウザで検査して、ドキュメントに余分なコードが追加されていないことを確認します。


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>

最も卑劣ではないが、うまくいくようで、多くの屈折矯正を節約しました。


5
実際にこれを行うことはありません。IEでは正常に動作しません。
jcbdrn 2015年

2
IEで断続的に、requireJSに含まれているスクリプトは、それらの変数が復元された後にrequireコマンドが来た場合でも、ウィンドウスコープから欠落していると定義していました。なぜこれが発生したのか理解できなかったため、このハッキーなソリューションを放棄しました。
jcbdrn

2
@jcbdrn IEだけではありません。私はそれが他のプラットフォームで起こるのを見ました。その理由は、HTML仕様では、同期スクリプトの実行順序が他の同期スクリプトと比較してのみ保証されているためです。同期スクリプト(またはその逆)と比較した非同期スクリプトの実行は保証されません。したがって、ここの回答に示されているコードでは、任意の2つのscript要素間で非同期スクリプトを実行することが可能です。
Louis

:編集する能力にインポートしているバンドルの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をロードした後にスクリプトがロードすることになります

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.