既存のAMDモジュールを再構築して、RequireJSが表示されているページと表示されていないページの両方で使用できるようにする必要があります。どのようにすればよいですか、サンプルコードはありますか?厳密な要件ではありませんが、グローバル名前空間を汚染しない方法であることが望ましいでしょう。
6 に答える
これはまったく悪い考えではありません。AMD/非AMD環境をサポートするためにJSライブラリが必要になることがよくあります。ソリューションのバリエーションの1つを次に示します。
!function (name, definition) {
if (typeof module != 'undefined') module.exports = definition()
else if (typeof define == 'function' && define.amd) define(name, definition)
else this[name] = definition()
}('reqwest', function () {
// Module here
});
唯一の欠点は、他の依存関係をリクエストできないことです。したがって、これは、以下のようなスタンドアロンライブラリでのみ役立ちます。
私は最近、このトピックに関する要点を書いたので、以下に関連するビットをコピーしました。ただし、詳細については、元の要点を確認してください。
次の定型文を使用すると、モジュールを1回記述して、CJS / NodeJ、AMD、またはブラウザグローバル環境で動作させることができます。
最適な用途...
- 名前空間(err、globals)コードからAMDまたはCJSモジュールのいずれかまたは両方に移行しています。
- ブラウザのグローバルをまだ除外することはできませんが、NodeJS(Mochaなど)を介してコードをテストする必要もあります。
メリットとトレードオフ
- AMD、CJS / NodeJS、およびなどのレガシーブラウザグローバルをターゲットにできる単一のモジュール形式
window.*
。 - 複数の依存関係を定義できます。
- CLI / NodeJSランナー(Mochaなど)を介して単体テストを実行します。
- CJS/NodeJSまたはAMDモジュールに段階的に移行する際の苦痛が少なくなります。
- あなたはJavaのような名前空間(例えばcom.company.package.module)をあきらめます-まあ、とにかくそれらは混乱しています。
- これ(UMD)は標準ではありません。公平を期すために、どちらもAMDではありません(これは明確に定義された仕様の規則です)。
- ボイラープレート(および醜い)の重要な量。
例
/**
* Creates a an "AppWidget" module that imports a "SingleDependency" constructor and exposes an "AppWidget" constructor.
*
* Allows you to access AppWidget as a CJS/AMD module (i.e. NodeJS or RequireJs):
*
* @example
* var AppWidget = require('app-widget')
*
* Allows you to access AppWidget as a legacy browser global:
*
* @example
* var AppWidget = window.AppWidget
*/
!(function (name, context, definition) {
if (typeof exports === 'object') { module.exports = definition(require); } else if (typeof define === 'function' && define.amd) { define(definition); } else { context[name] = definition(); }
}).call(this, 'AppWidget', this, function (require) {
'use strict'
// imports
var SingleDependency = (typeof require === 'function') ? require('./single-dependency') : window.SingleDependency;
var singleDependency = new SingleDependency();
function AppWidget() {}
AppWidget.prototype.start = function () {};
// exports
return AppWidget;
});
UMDをチェックしてください。そこにあなたの目的に適したパターンを見つける必要があります。テンプレートはやや醜いですが、機能します。
これはかなり悪い考えだと思います。
それが機能することを確認するためにあなたが取らなければならないあなたの可能なステップ:
- すべてのモジュールの依存関係がそのページにロードされていることを確認してください(jQuery、Backboneなど)
- モジュールを実行する必要があることがわかっている順序でページにモジュールを含めます
- 別のモジュールの依存関係であるモジュールが、「インポート」モジュールが期待し、そのコードで参照するのと同じ名前のグローバル変数を作成することを確認してください
- モジュールが同じ名前で依存関係(他のモジュールを含む)を参照していることを確認してください
define
モジュールのファクトリ関数を実行するグローバルメソッドをオーバーライド/作成します
そして、それはあなたがしなければならないことのほんの一部です。RequireJSページに対してAMDに準拠する必要がある(または少なくともそのshim
構成に含まれている)必要があるが、RequireJS以外のページに対してもグローバルである必要があるサードパーティについてはどうでしょうか。
簡単に言えば、IMO、既存のコードをAMDバージョンに作り直して、モジュールを非AMDにする方が簡単です。
Simon Smithsの回答に基づいて、モジュールの依存関係を扱いました。
(function (root, factory) {
if (typeof exports === "object") {
module.exports = factory();
} else if (typeof define === "function" && define.amd) {
define(['jquery', 'ol'], factory);
} else {
root.module_name = factory();
}
}(this, function (_$, _ol) {
return new function () {
// supposed that window.ol and window.$ are defined
var ol = goog.isDef(_ol) ? _ol : window.ol;
var $ = goog.isDef(_$) ? _$ : window.$;
}
}));
機能はどこgoog.isDef
にありますかGoogle Closure
:
goog.isDef = function(val) {
return val !== void 0;
};
それが誰かを助けることを願っています。
Browserifyをチェックしてください。これにより、AMD/JSコードからすべての依存関係が埋め込まれた単一のスタンドアロン.jsファイルが作成されます。
次に、2つのバージョンのコードを出荷できます。1つはAMDユーザー用で、もう1つは「オールドスクール」jsユーザー用です。