web-dev-qa-db-ja.com

ブラウザー内JavaScriptにノードスタイルが必要ですか?

Nodeのrequireと同じ柔軟性/モジュール性/使いやすさを提供するブラウザ内JavaScript用のライブラリはありますか?

詳細を提供するには:requireが優れている理由は次のとおりです。

  1. コードを他の場所から動的にロードできるようにします(私の意見では、HTML内のすべてのコードをリンクするよりもスタイル的に優れています)
  2. モジュールを構築するための一貫したインターフェースを提供します
  3. モジュールが他のモジュールに依存するのは簡単です(たとえば、jQueryを必要とするAPIを記述して、jQuery.ajax()を使用できます
  4. 読み込まれたjavascriptはscopedです。つまり、var dsp = require("dsp.js");を読み込むことができ、_dsp.FFT_にアクセスでき、ローカルに干渉しません_var FFT_

これを効果的に行うライブラリをまだ見つけていません。私が使用する傾向がある回避策は次のとおりです。

  • coffeescript-concat -他のjsを必要とするのは簡単ですが、コンパイルする必要があるため、高速開発(テスト中のAPIのビルドなど)にはあまり適していません

  • RequireJS -人気があり、簡単で、1から3を解決しますが、スコープの欠如は本当の取引ブレイカーです( head.js は欠けているという点で似ています同様に、 LABjs はロードでき、.wait()は依存関係の問題を緩和しますが、それでもスコーピングは行いません)

私が知る限り、javascriptの動的および/または非同期ロードには多くのソリューションがあるように見えますが、HTMLからjsをロードするのと同じ範囲の問題を抱えている傾向があります。何よりも、私はグローバルな名前空間をまったく汚染しないjavascriptをロードする方法を望んでいますが、それでも私はライブラリをロードして使用することができます(ノードの要求と同じように)。

EDIT(MY ANSWER):これを書いて以来、私は RequireJS (より明確なドキュメントが追加されました)を広く使用しました。私の意見では、RequireJSは本当に正しい選択でした。私と同じように混乱している人々のためにシステムがどのように機能するかを明確にしたい:

requireを日常の開発で使用できます。モジュールは、関数(通常はオブジェクトまたは関数)によって返されるものであれば何でもよく、パラメーターとしてスコープされます。 _r.js_を使用して、プロジェクトを展開用の単一ファイルにコンパイルすることもできます(実際には、requireはスクリプトを並行してロードできますが、これはほとんど常に高速です)。

RequireJSとbrowserify(tjamesonが提案するクールなプロジェクト)のようなノードスタイルのrequireの主な違いは、モジュールの設計方法と要求方法です。

  • RequireJSはAMD(非同期モジュール定義)を使用します。 AMDでは、requireはロードするモジュール(javascriptファイル)のリストとコールバック関数を取ります。各モジュールをロードすると、各モジュールをコールバックのパラメーターとしてコールバックを呼び出します。したがって、それは本当に非同期であり、したがってWebに適しています。
  • NodeはCommonJSを使用します。 CommonJSでは、requireは、モジュールをロードしてオブジェクトとして返すブロック呼び出しです。これは、Nodeに対しては正常に機能します。ファイルはファイルシステムから読み取られますが、これは十分に高速ですが、ファイルの同期ロードには非常に長い時間がかかるため、Webでの動作は不十分です。

実際には、多くの開発者は、AMDを見る前にNode(したがってCommonJS)を使用していました。さらに、多くのライブラリ/モジュールはCommonJS用に(exportsオブジェクト)(AMDではなくdefine関数からモジュールを返すことにより)。したがって、多くのNode-turned-web開発者はWeb上でCommonJSライブラリを使用したいと考えています。 _<script>_タグがブロックされているbrowserifyなどのソリューションは、CommonJS(ノード)モジュールを取り込んで、スクリプトタグに含めることができるようにそれらをラップします。

したがって、Web用の独自のマルチファイルプロジェクトを開発している場合、RequireJSはWeb用のモジュールシステムであるため、強くお勧めします(公正な開示では、AMDはCommonJSよりもはるかに自然だと思います)。最近、RequireJSで基本的にCommonJS構文を使用できるようになったため、区別はそれほど重要ではなくなりました。さらに、RequireJSを使用して、AMDモジュールをNode(ただし、私は node-AMD-loader を好みます)でロードできます。

71
Alex Churchill

ender を確認してください。これの多くを行います。

また、 browserify はかなり良いです。 require-kiss を使用しましたが、動作します。おそらく他にもあります。

RequireJSについてはわかりません。それはノードのものと同じではありません。他の場所からの読み込みで問題が発生する場合がありますが、動作する可能性があります。提供メソッドまたは呼び出すことができるものがある限り。

TL; DR-browserifyまたはrequire-kissをお勧めします。

更新:

require-kissは現在死んでおり、著者はそれを削除しました。それ以来、RequireJSを問題なく使用しています。 require-kissの作者は pakmanagerpakman を書きました。完全な開示、私は開発者と協力しています。

個人的には、RequireJSの方が好きです。デバッグがはるかに簡単で(開発中に個別のファイルを、実稼働中に1つのデプロイ済みファイルを使用できます)、堅牢な「標準」に基づいて構築されます。

15
beatgammit

Javascriptファイルの非同期および同期ロードを可能にする小さなスクリプトを作成しました。依存関係はなく、Node.jsおよびCommonJSと互換性があります。複数のモジュールを1つのファイルにバンドルして、実稼働サーバーでのHTTP要求を減らすこともできます。使い方はとても簡単です:

<script type="text/javascript" src="require.js"></script>
<script type="text/javascript">
    var ModuleA = require('modulea') // Sync loading of a script in the module directory
    ModuleA.funcA();

    require('./path/moduleb.js', callbackB); // Async loading of a script anywhere else
    function callbackB(ModuleB) {
        ModuleB.funcB();
    }
</script>

詳細とコードは私のブログで見つけることができます: http://pixelsvsbytes.com/2013/02/js-require-for-browsers-better-faster-stronger/ コードもオンGitHub: https://github.com/letorbi/tarp.require

13
Torben

Ilya Kharlamov great answer のバリエーション。chrome開発者ツールを使用してNiceを再生するためのコードがいくつかあります。

//
///- REQUIRE FN
// equivalent to require from node.js
function require(url){
    if (url.toLowerCase().substr(-3)!=='.js') url+='.js'; // to allow loading without js suffix;
    if (!require.cache) require.cache=[]; //init cache
    var exports=require.cache[url]; //get from cache
    if (!exports) { //not cached
            try {
                exports={};
                var X=new XMLHttpRequest();
                X.open("GET", url, 0); // sync
                X.send();
                if (X.status && X.status !== 200)  throw new Error(X.statusText);
                var source = X.responseText;
                // fix (if saved form for Chrome Dev Tools)
                if (source.substr(0,10)==="(function("){ 
                    var moduleStart = source.indexOf('{');
                    var moduleEnd = source.lastIndexOf('})');
                    var CDTcomment = source.indexOf('//@ ');
                    if (CDTcomment>-1 && CDTcomment<moduleStart+6) moduleStart = source.indexOf('\n',CDTcomment);
                    source = source.slice(moduleStart+1,moduleEnd-1); 
                } 
                // fix, add comment to show source on Chrome Dev Tools
                source="//@ sourceURL="+window.location.Origin+url+"\n" + source;
                //------
                var module = { id: url, uri: url, exports:exports }; //according to node.js modules 
                var anonFn = new Function("require", "exports", "module", source); //create a Fn with module code, and 3 params: require, exports & module
                anonFn(require, exports, module); // call the Fn, Execute the module
                require.cache[url]  = exports = module.exports; //cache obj exported by module
            } catch (err) {
                throw new Error("Error loading module "+url+": "+err);
            }
    }
    return exports; //require returns object exported by module
}
///- END REQUIRE FN
7
Lucio M. Tato
(function () {
    // c is cache, the rest are the constants
    var c = {},s="status",t="Text",e="exports",E="Error",r="require",m="module",S=" ",w=window;
    w[r]=function R(url) {
        url+=/.js$/i.test(url) ? "" : ".js";// to allow loading without js suffix;
        var X=new XMLHttpRequest(),module = { id: url, uri: url }; //according to the modules 1.1 standard
        if (!c[url])
            try {
                X.open("GET", url, 0); // sync
                X.send();
                if (X[s] && X[s] != 200) 
                    throw X[s+t];
                Function(r, e, m, X['response'+t])(R, c[url]={}, module); // Execute the module
                module[e] && (c[url]=module[e]);
            } catch (x) {
                throw w[E](E+" in "+r+": Can't load "+m+S+url+":"+S+x);
            }
        return c[url];
    }
})();

ブロッキングのために本番環境で使用しない方が良い。 (node.jsでは、require()はブロッキング呼び出しです)。

5
Ilya Kharlamov

Require-stub —ブラウザにノード準拠のrequireを提供し、モジュールと相対パスの両方を解決します。 TKRequire(XMLHttpRequest)と同様のテクニックを使用します。結果のコードは、require-stubは、watchifyの代わりとして使用できます。

1
dy_

Webmake Node-styleモジュールをブラウザにバンドルして、試してみてください。

1
Mariusz Nowak

これは、相対パスを使用したモジュールの再帰的なロードを可能にするLucio M. Tatoの素晴らしい答えの拡張です。

ソリューションを収容するgithubプロジェクト とその使用方法の例を次に示します。

https://github.com/trausti/TKRequire.js

TKRequire.jsを使用するには、ヘッダーに次の行を含めます

<script type = "text/javascript" src = "./ TKRequire.js"> </ script>

次に、node.jsと同じようにモジュールをロードします。

var MyModule = require( "./ relative/path/to/MyModule.js");