1

概要

RequireJSを使用し てサイトをAMDに変換しようとしています。サイトの大部分は、別のモジュール (主にユーティリティ メソッド) で定義されたグローバル変数に依存しています。モジュールは常にコンテンツ スクリプトの前にロードされるとは限らないため、これは開発者にとって深刻な問題につながります。

理想的な結果

特定のモジュールが読み込まれるまで、これらのページ内スクリプトが解析されないようにする方法が必要です。これにより、チーム メンバーは時間の許す限りゆっくりとそれらを削除できます。

リサーチ

  1. curl.jsには、いくつかのスクリプトを同期モードでロードする方法があることに気付きました。
  2. 以前はサポートされていたと思っていましたが、RequireJS 2+ に似たものは見つかりませんでした。(私の git foo は十分に強力ではありません。)

注意事項

  1. dev モードでスクリプト タグを介してモジュールをロードできることは承知していますが、モジュールを 2 か所にリストする必要があるため、ロードしないほうがよいでしょう。

私が試したこと

そこで私はポーリング ソリューションを生成しようとしました。これは大雑把なタイミングの while ループを実行し、その後ブレークアウトしてコールバックを実行します。これが私の実装です:

(function (global) { // Making this into a global, so I don't need to wait for the loader's extra timeout. 
    var undef;

    /**
     * Simple args getter.
     *
     * @param {*} arg Used if defined.
     * @param otherwise Used if arg is not defined.
     * @return {*}
     */
    var arg = function (arg, otherwise) {
        return arg !== undef ? arg : otherwise;
    };

    /**
     * Locks up the main thread as soon as the current thread completes.
     *
     * @param {number} time
     */
    var lock = function (time) {
        setTimeout(function () {
            var start = +(new Date),
                current = 0;
            console.log('Locking thread at %d', start);

            start += time;
            while (start > (current = +(new Date))) {
                console.log('tick');
            }

            console.log('Unlocking thread at %d', current);
        }, 0);
    };

    /**
     * Locks up the main thread until a condition is met, releasing it
     * momentarily to allow other "threads" to advance.
     *
     * @param {Function} condition
     * @param {number} [checkInterval=50] How long
     */
    var lockThreadUntil = global.lockThreadUntil = function (condition, checkInterval, releaseDuration) {
        checkInterval = arg(checkInterval, 50);
        releaseDuration = arg(releaseDuration, 0);

        var id = setInterval(function () {
            if (!condition()) {
                lock(checkInterval);
            } else {
                clearInterval(id);
            }
        }, releaseDuration);
    };

    define(function () {
        return lockThreadUntil;
    });
})(this);

ページ上(グローバルを作成するモジュールでテストしました):

(function (global) {
    lockThreadUntil(function () {
        var isLoaded = !!global.path && !!global.path.toModule;
        if (!isLoaded) {
            return false;
        }

        console.log('Is loaded!');
        return true;
    }, 1000);
})(this);

コンテンツ内スクリプトでは、次のようになります。

console.log('Was needed!');

これにより、スクリプトをロードする時間を与えながら DOM がほとんど進まず、コンテンツ内スクリプトより先に解析スタックに入ることができるようになることを期待していました。残念ながら、コンテンツ内スクリプトが最初に起動しているようです。

要約

私は提案を受け入れます。私が考えているオプションには次のものがあります(どちらもひどいようです):

  • 歯を食いしばり、スクリプト タグを使用します。
  • RequireJS ロード メソッドを飲み込み、xhr 実装に置き換えます。
4

1 に答える 1

0

レガシ コードに require js shim機能を使用し、RequireJS がすべて (DOM 内のスクリプト タグを含む) をロードできるようにすることをお勧めします。Shim を使用すると、本質的にレガシー ブラウザー グローバル ファイルの AMD バージョンを作成できます。shim 構成を使用すると、shim モジュールの依存関係を指定したり、エクスポートされたブラウザー グローバルを識別したりできます。

レガシー ファイルABが DOM にスクリプト タグとしてあり、 BがファイルAに依存している (スクリプト タグが後にある) とします。また、ABの両方が AMD 形式のユーティリティ モジュールLibに依存しているとします。ABのスクリプト タグをDOM から削除し、次のような require js 構成ブロックを追加します。

requirejs.config({
  shim: {
    'A': ['Lib'],
    'B': ['Lib', 'A']
  }
});

これにより、基本的に、AMD モジュール ライブラリが解析された後に、RequireJS がレガシー スクリプトをロードするようになります。ここでは、すべてのライブラリ AMD モジュールが単一のスーパーモジュールLibを介して必要になる可能性があると想定して、例を単純化しました。

shim のドキュメントを読んで、モジュールがエクスポートするもの (グローバル オブジェクトの観点から) を require js に伝えて、shim をより完全にする方法についても説明しています。

警告:これは開発モードでのみ機能します。RequireJS オプティマイザーを実行しようとしても、標準の AMD モジュールに対する shimmed モジュールの依存関係により、結果は機能しません (ここで説明されているように)。

また、このソリューションでは、必要に応じて shim 構成の依存関係を使用して、DOM 内の各スクリプト タグの順序を手動でジグする必要があります (たとえば、A に依存させることで B を A に追従させました)。以前は RequireJSオーダーを使用できました。これは、スクリプト間の真の依存関係を解決し、将来的にAMDへの完全な変換を少し簡単にするのに役立つため、悪いことではありません。

于 2012-08-05T18:00:09.210 に答える