2016-04-06 3 views
4

JavaScriptでモジュールを作成しており、ブラウザとサーバー(ノード付き)の両方で使用できます。それをモジュールと呼ぶことができます。そのモジュールは、という依存モジュールと呼ばれる別のモジュールのメソッドの恩恵を受けると言います。これらのモジュールの両方がla CommonJSスタイルà、ブラウザとサーバーの両方で使用されるように書かれていますパッケージ化ブラウザ/サーバCommonJSモジュール(依存関係あり)

module.js

if (typeof module !== 'undefined' && module.exports) 
    module.exports = Module; /* server */ 
else 
    this.Module = Module; /* browser */ 

dependancy.js

if (typeof module !== 'undefined' && module.exports) 
    module.exports = Dependancy; /* server */ 
else 
    this.Dependancy = Dependancy; /* browser */ 

明らかに、従属性は、ブラウザですぐに使用できます。しかし、モジュールvar dependancy = require('dependency');というディレクティブが含まれていると、モジュールをメンテナンスするのが面倒になります。

私はこのように、私はモジュール依存のためのグローバルなチェックを行うことができることを知っている:

var dependancy = this.Dependancy || require('dependancy'); 

しかし、それは私のモジュールは、ブラウザのインス​​トール用の2つの追加要件有することを意味する:

  • ユーザーはdependency.jsファイルを<script> iとして含める必要がありますnはその文書
  • およびユーザーは、このスクリプトは、これら二つの要件を追加すると、CommonJSのような気楽なモジュラーフレームワークのアイデアをスローmodule.js

前にロードされていることを確認する必要があります。

私のための他のオプションは、私がbrowserifyを使用してバンドルさdependency.jsと私のモジュールパッケージにおける第二、コンパイルされたスクリプトが含まれていることです。次に、ブラウザのスクリプトを使用しているユーザーにこのスクリプトを含めるように指示し、サーバー側のユーザーはpackage.jsonに記載されているバンドルされていない入力スクリプトを使用します。これは最初の方法よりも好ましい方法ですが、ライブラリを変更するたびに(GitHubにアップロードする前など)実行しなければならないプリコンパイルプロセスが必要です。

私が考えていない他の方法はありますか?

+0

これはひどい考えです。サーバーとブラウザはセキュリティ上の理由から同じライブラリを共有してはいけません。そのため、最初は両方を必要としています。あなたの依存関係の1つは、ユーザーの電子メールやパスワードなどを公開しています。悲惨なことだ。 – Val

+0

@Valセキュリティに触れないサーバ側とブラウザ側の両方に使用できる多くの共通ライブラリがあります。ケースインポイント、[async](https://github.com/caolan/async)ライブラリ。さらに、この場合、** Module **と** Dependency **の両方が自分で作成されています。 – shennan

答えて

1

もちろん、同じモジュールを使用して、両側にの依存関係を設定することもできます。あなたはそれをより良く指定する必要があります。これは私の使用方法です:

これは単なる非常に基本的なサンプルです。関数を返すか、関数をインスタンス化するか、好きなことをすることができます。私の場合、私はオブジェクトを返しています。

ここではDependencyクラスとしましょう。あなたのModuleクラスは、ほとんど同じに見えるはずですが、、それは次のようにDependencyへの依存関係を持っている必要があります。これは、簡体CommonJSラッパーと呼ばれるRequireJSで

function (require, exports, module) { 
    var dependency = require('Dependency'); 
} 

http://requirejs.org/docs/api.html#cjsmodule

require文がありますのであなたのコードの初めに、それは依存関係としてマッチングされますので、それは遅れてロードされるか、またはあなたがそれを最適化すれば - 依存関係として早く(define(definition)からdefine(['Dependency'], definition)に自動的に変換されます)

ここで唯一の問題は、をファイルと同じに保つことです。 (場合-他)が必要ですが、必要では動作しませんネストされたことを覚えておいてください(ドキュメントを読む)ので、私のような何かしなければならなかった:これは私のために完全に働いた

var dependency; 
try { 
    dependency = require('./Dependency'); // node module in the same folder 
} catch(err) { // it's not node 
    try { 
     dependency = require('Dependency'); // requirejs 
    } catch(err) { } 
} 

を。これは少し難解ですが、終わりには別々のモジュールを別々のファイルに入れて両端で使うことができますなしチェックやハックはありません。すべての依存関係は仕事です魅力のように:)

+0

[RequireJS](http://requirejs.org/)は[AMD](https://en.wikipedia.org/wiki/Asynchronous_module_definition)を使用しています。これはNodeのvanilla CommonJSの使用とサーバ側で競合しないでしょうか?私はそれを意味するわけではありませんが、あなたの経験では、[Browserify](http://browserify.org/)を使ってモジュールをライン? – shennan

+0

コードをトレースすると、すべてのチェックを行い、AMDモジュールは 'define'を使用し、ノードの宣言方法は' module.exports'を使用することがわかります。したがって、彼らはちょうど箱からうまく動作します:)あなたがモジュールを作ることを試みるので、クライアント側ですでに 'RequireJS'を使用していると何とか決めたことはとても残念です。私のここでの誤り –

+0

browserifyはcommonjを使用していると言われていますので、うまくいけばまっすぐに働くはずです:) –

1

webpackバンドラーを見てください。 モジュールを書き出して、モジュールの書き出しによって書き出すことができます。それから、サーバーではmodule.exportを持っている場所とwebpackでブラウザをビルドする場所を使用できます。設定ファイルの使用が最適です。

module.exports = { 
entry: "./myModule", 
output: { 
    path: "dist", 
    filename: "myModule.js", 
    library: "myModule", 
    libraryTarget: "var" 
} 
}; 

これはmyModuleを使用してmyModule.jsファイルにエクスポートします。内部のモジュールは、myModule(ライブラリフラグ)という名前のvar(libraryTargetフラグ)に割り当てられます。

それは束ねためcommonJSモジュール、戦争、この機能

としてエクスポートすることができるが、ノードのスクリプトであり、このフラグの値は、文法的に設定することができます。

externalsフラグを見てください。いくつかの依存関係に対して特別な振る舞いをしたい場合に使用されます。たとえば、反応コンポーネントを作成していて、モジュールにはそれを必要としたいのですが、すでにバンドルされているためにバンドルしているときではありません。

あなたが探しているものです。

+0

あなたの答えをありがとう。 [Webpack](http://webpack.github.io/docs/configuration.html)は面白いプロジェクトのようです。一般的な問題に対する全体的なアプローチのように見えますが、私の言うとおり、私の特定のユースケースでは少し残忍に思えます。 – shennan

2

現在のところ、この2つの回答は非常に役に立ち、私の現在のソリューションに到達するのに役立ちました。しかし、私のコメントによると、移植性と使いやすさ(クライアントとモジュール保守者の両方)の私の特定の要件を十分に満たすものではありません。

最終的には、browserifyコマンドラインインターフェイスの特定のフラグがあり、モジュールをバンドルしてグローバル変数として公開し、(必要に応じて)RequireJS内で使用することができます。 Browserify(およびその他)は、このユニバーサルモジュール定義(UMD)を呼び出します。もう少し詳しくはhereです。

browserifyコマンドで--standaloneフラグを渡すことで、自分のモジュールをUMD用に簡単に設定できます。

So ...

ここpackage.jsためのモジュールです:私のモジュールのルートに、私は、コマンドラインでこれを実行することができたときに、そう

{ 
    "name": "module", 
    "version": "0.0.1", 
    "description": "My module that requires another module (dependancy)", 
    "main": "index.js", 
    "scripts": { 
    "bundle": "browserify --standalone module index.js > module.js" 
    }, 
    "author": "shennan", 
    "devDependencies": { 
    "dependancy": "*", 
    "browserify": "*" 
    } 
} 

:依存関係をバンドル

$ npm run-script bundle 

1つのファイルにまとめ、UMDの方法論に従って公開します。 RequireJS

<script src="require.js"></script> 
<script> 
    requirejs(['module.js'], function (Module) { 
    /* use Module */ 
    }); 
</script> 
0で

NodeJS

var Module = require('module'); 
/* use Module */ 

ブラウザバニラ

<script src="module.js"></script> 
<script> 
    var Module = module; 
    /* use Module */ 
</script> 

ブラウザ:これは私が3つの異なる方法でモジュールをブートストラップすることができることを意味します

皆様のご意見をお寄せいただきありがとうございます。すべての回答が有効です。異なるユースケースでは異なる解決策が必要になるため、誰もがそれらを試してみることをお勧めします。