5

お客様の Web サイトに組み込む JavaScript プラグインを開発しました。私が作成したプラグインは、jQuery 1.8.2 と KnockoutJS v3.0.0 の 1 つの大きなパッケージとしてバンドルされ、クライアントに配信されるいくつかの外部ライブラリに依存しています。

プラグインはほとんどのサイトで正常に動作しますが、ホスト サイトが RequireJS を使用している場合、KnockoutJS が RequireJS の存在を自動的に検出して使用しようとするため、パッケージの読み込みに失敗します。スローされるエラーは次のとおりです。

Mismatched anonymous define() module

明らかに、RequireJS サイトでエラー メッセージの「説明」を見つけました。残念ながら、それを回避する方法がわかりません。KnockoutJS ライブラリのローカル コピーで、問題のある行を見つけました。

(function(factory) {
    // Support three module loading scenarios
    if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
        // [1] CommonJS/Node.js
        var target = module['exports'] || exports; // module.exports is for Node.js
        factory(target);
    } else if (typeof define === 'function' && define['amd']) {
        // [2] AMD anonymous module
        define(['exports'], factory);
    } else {
        // [3] No module loader (plain <script> tag) - put directly in global namespace
        factory(window['ko'] = {});
    }
}

このファイルを手動で編集して、条件 [2] が実行されず、条件 [3] のみが実行されるようにすると、すべて正常に動作します。もちろん、これはやりたくありません。外部ライブラリを編集する必要があるためです。後でアップグレードできるように、外部ライブラリを元の状態に保ちたいと考えています。

これを機能させる方法があるかもしれないと感じていますが、RequireJS の仕組みがわかりません。明らかに、KnockoutJS は RequireJS とうまくやろうとしていますが、私の場合は失敗しています。この場合、RequireJS は存在しますが、KnockoutJS を使用する必要はありません。

これら 2 つのライブラリを並行して動作させるにはどうすればよいですか?

編集

自分のライブラリが読み込まれるタイミングと、ホスト サイトが既に読み込まれている他のすべてのライブラリを制御することはできません。実際、ほとんどの場合、私のプラグインが組み込まれます。それは、WordPress、Webs.com、Weebly などのひどい WYSIWYG プラットフォームを使用する Web 開発経験のない人によるものです。 body 要素のどこかに含まれている場合もあります。

また、明確にするために、私のライブラリは RequireJS を使用していません。私のライブラリを使用しようとしている顧客の 1 人が RequireJS を使用しており、私のライブラリが含まれると、KnockoutJS (私のライブラリにバンドルされていますが、まだホスト サイトにはありません) が例外をスローすることがあります。自分自身を RequireJS に登録します (または、少なくともそれは例外に関する私の推測です)。

原則として、コードが依存するライブラリをオンデマンドでロードすることに反対しているわけではありませんが、実際には、ライブラリをロードするために追加の要求/応答サイクルが必要になるため、ユーザーのエクスペリエンスが遅くなります。

4

1 に答える 1

4

最も簡単な方法は、 requirejs の前にノックアウトをロードすることでしょう。ko は require が存在することを検出しなくなり、オプション [3] を使用します。これができない場合、もう 1 つのオプションは、プラグインと ko ファイルを require 階層に追加することです。

プラグインが次のようになったとしましょう。

(function(ko){

//stuff
ko.applyBindings({});

})(ko) 

これを次のように変更する必要があります。

require([
    "knockout-3.0.0.js" // this should be the url you use for knockout
    ], function(ko){
       //stuff
       ko.applyBindings({});
})

また、knockout.js ファイルを別のタグとしてロードしないでください。Require がロードを処理します。もちろん、サーバーは「knockout-3.0.0.js」の URL を配信できる必要があります。これがrequireの仕組みです。これは、require の配列パラメーターの要素として渡した URL を読み込み、それらが返すものをパラメーターとして関数に渡します。

プラグイン ファイルと ko ファイルの両方を 1 つのファイルに縮小/バンドルする必要がある場合は、reuquirejs 縮小/最適化ツール ( http://requirejs.org/docs/optimization.html ) を使用できます。依存関係ツリーをナビゲートし、すべてのモジュールを内部に含む js ファイルを 1 つだけ出力します。ここでの 1 つの癖: ミニファイヤが機能するには .js 拡張子を削除する必要があります。詳細についてはドキュメントを参照してください。

また、require で ko を使用する方法に関するその他のドキュメントは、http: //knockoutjs.com/documentation/amd-loading.htmlにあります。

編集、操作編集後:

わかりましたので、この場合は別のスコープを作成する必要があります。このスコープで、必要なことを行うことができます。ファイル内の ko コードをコピーする必要がありますが、このようにすれば、少なくとも 1 つのファイルを取得できます。

したがって、最初にスコープを作成します。

(function(){

})()

次に、内部に ko コードをコピーします。

(function(){

//ko code here, should be a single, minified line

})()

次に、ko をだましてオプション 3 を使用させる必要があるため、次のようにします。

(function(){

var define = null; //so define will no longer be a function, don't forget the var
var require = null;
//ko code here, should be a single, minified line

})()

ページ全体で ko を使用したくない場合は、必要に応じて、上記の手順で window を再割り当てすることもできます。

次に、プラグイン コードを追加します。

(function(){

var define = null; //so define will no longer be a function, don't forget the var
var require = null;
//ko code here, should be a single, minified line

//plugin code here;

})()
于 2013-11-01T22:19:22.630 に答える