95

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

詳細を提供するために:理由requireはとても良いですそれはそれです:

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

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

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

  • RequireJS-人気があり、わかりやすく、1〜3を解決しますが、スコープの欠如は本当に大きな問題です(head.jsは、スコープがないという点で似ていると思いますが、使用する機会はありませんでした。同様に、LABjsは依存関係の問題をロードして緩和できます.wait()が、それでもスコープは実行されません)

私の知る限り、JavaScriptの動的および/または非同期ロードには多くの解決策があるように見えますが、HTMLからjsをロードするのと同じスコープの問題が発生する傾向があります。何よりも、グローバル名前空間をまったく汚染しないが、ライブラリをロードして使用できるようにする(ノードの要求と同じように)javascriptをロードする方法が必要です。

2020年の更新: モジュールはES6で標準になり、2020年半ばの時点で、ほとんどのブラウザーでネイティブにサポートされています。モジュールは、同期と非同期(Promiseを使用)の両方のロードをサポートします。私の現在の推奨事項は、ほとんどの新しいプロジェクトでES6モジュールを使用し、トランスパイラーを使用してレガシーブラウザー用の単一のJSファイルにフォールバックすることです。

一般的な原則として、今日の帯域幅も通常、私が最初にこの質問をしたときよりもはるかに広くなっています。したがって、実際には、ES6モジュールで常にトランスパイラーを使用し、ネットワークではなくコード効率に注力することを合理的に選択する場合があります。

以前の編集(またはES6モジュールが気に入らない場合):これを書いた後、私はRequireJSを広範囲に使用しました(これにより、より明確なドキュメントが作成されました)。私の意見では、RequireJSは本当に正しい選択でした。私と同じように混乱している人々のためにシステムがどのように機能するかを明らかにしたいと思います。

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

RequireJSとnode-stylerequirelike browserify(tjamesonによって提案されたクールなプロジェクト)の使用の主な違いは、モジュールの設計と要件の方法です。

  • RequireJSはAMD(非同期モジュール定義)を使用します。AMDでは、requireロードするモジュール(javascriptファイル)のリストとコールバック関数を取ります。各モジュールをロードすると、コールバックのパラメーターとして各モジュールを使用してコールバックを呼び出します。したがって、これは真に非同期であるため、Webに最適です。
  • ノードはCommonJSを使用します。CommonJSではrequire、モジュールをロードしてオブジェクトとして返すブロッキング呼び出しです。これは、ファイルがファイルシステムから読み取られるため、ノードでは正常に機能します。これは十分に高速ですが、ファイルの同期ロードにかかる時間が大幅に長くなる可能性があるため、Webではうまく機能しません。

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

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

4

7 に答える 7

21

エンダーをチェックしてください。これは多くのことを行います。

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

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

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


アップデート:

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

個人的にはRequireJSの方が好きです。デバッグがはるかに簡単で (開発環境では個別のファイルを使用し、運用環境では単一のデプロイ ファイルを使用できます)、堅実な "標準" に基づいて構築されています。

于 2011-08-07T08:26:26.220 に答える
17

Javascript ファイルの非同期および同期ロードを可能にする小さなスクリプトを作成しました。これは、ここで役立つかもしれません。依存関係がなく、Node.js および CommonJS と互換性があります。インストールはとても簡単です:

$ npm install --save @tarp/require

次に、HTML に次の行を追加して、main-module をロードします。

<script src="/node_modules/@tarp/require/require.min.js"></script>
<script>Tarp.require({main: "./scripts/main"});</script>

メインモジュール (もちろんサブモジュールも) 内ではrequire()、CommonJS/NodeJS から知っているように使用できます。完全なドキュメントとコードはGitHub にあります。

于 2012-07-21T00:40:34.847 に答える
12

Ilya Kharlamov の素晴らしい回答のバリエーションで、chrome 開発者ツールでうまく機能するようにするためのコードがいくつかあります。

//
///- 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
于 2013-10-28T00:04:56.667 に答える
5
(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() はブロッキング呼び出しです)。

于 2013-08-05T01:29:06.230 に答える
1

Require-stub — ブラウザーでノード準拠requireを提供し、モジュールと相対パスの両方を解決します。TKRequire (XMLHttpRequest) と同様の技術を使用します。結果のコードは完全にブラウザ化require-stub可能であり、 watchify.

于 2015-01-11T07:15:58.767 に答える
0

Webmakeは Node スタイルのモジュールを Browser にバンドルしています。試してみてください。

于 2012-07-26T18:58:49.270 に答える