2013-11-23 4 views
43

これはやや長いですが、混乱を説明するためにコード例が必要になります。その後、私は次のための答えに興味を持っています:複数のgrunt-browserifyバンドルで相対パスエイリアスを管理するにはどうすればよいですか?

  1. は、どのように私の代わりにrequire('../../src/module')またはrequire('./module')require('module')を使用していますか?
  2. ./index.jsspec/specs.jsに再利用するにはどうすればいいですか? (そして、入力モジュールとしてsrc/app.jsが実行されないようにする)。

すでにいくつかのブラウザベースのプロジェクトを開始しており、browserifyとgruntが大好きです。しかし、各プロジェクトは私の開発/学習曲線の同じポイントで死ぬ。ミックスにテストを追加し、2つのbrowserifyバンドル(とspec/specs.js)を管理しなければ、システム全体が崩れます。私が説明します:

私はgrunt-browserifyを使用して、私の最初のディレクトリを設定します。

. 
├── Gruntfile.js 
├── index.js (generated via grunt-browserify)  [1] 
├── lib 
│   ├── jquery 
│   │   └── jquery.js        [2] 
│   └── jquery-ui 
│    └── jquery-ui.js       [3] 
├── spec 
│   ├── specs.js (generated via grunt-browserify) [4] 
│   └── src 
│    ├── spec_helper.js (entry) 
│    └── module_spec.js (entry) 
└── src 
   ├── app.js (entry) 
   └── module.js 
  1. 1つのエントリファイル(src/app.js)を使用し、すべての必要モジュールをバンドルするコードの散歩を行います。
  2. browserify-shimから別名jqueryを使用します。
  3. シームなしでjquery-uiにエイリアスされています(var $ = require('jquery')の後に必要)。
  4. spec/srcのすべてのヘルパーファイルとスペックファイルをエントリモジュールとして使用します。
私は私の設定ステップスルーます

browserify: { 
    dist: { 
    files: { 
     'index.js': ['src/app.js'] 
    } 
    } 
} 

// in app.js 
var MyModule = require('./module'); // <-- relative path required?! 

ハッピー

今追加jqueryの:

browserify: { 
    options: { 
    shim: { 
     jquery: { 
     path: 'lib/jquery/jquery.js', 
     exports: '$' 
     } 
    }, 
    noParse: ['lib/**/*.js'], 
    alias: [ 
     'lib/jquery-ui/jquery-ui.js:jquery-ui' 
    ] 
    }, 
    dist: { 
    files: { 
     'index.js': ['src/app.js'] 
    } 
    } 
} 

// in app.js 
var $ = require('jquery'); 
require('jquery-ui'); 
var MyModule = require('./module'); 

ハッピー

今追加スペック:

options: { 
    shim: { 
    jquery: { 
     path: 'lib/jquery/jquery.js', 
     exports: '$' 
    } 
    }, 
    noParse: ['lib/**/*.js'], 
    alias: [ 
    'lib/jquery-ui/jquery-ui.js:jquery-ui' 
    ] 
}, 
dist: { 
    files: { 
    'app.js': 'src/app.js' 
    } 
}, 
spec: { 
    files: { 
    'spec/specs.js': ['spec/src/**/*helper.js', 'spec/src/**/*spec.js'] 
    } 
} 

// in app.js 
var $ = require('jquery'); 
require('jquery-ui'); 
var MyModule = require('./module'); 

// in spec/src/module_spec.js 
describe("MyModule", function() { 
    var MyModule = require('../../src/module'); // <-- This looks like butt!!! 
}); 

悲しい

要約する:どのように私は...

  1. 利用require('module')の代わりに、require('../../src/module')またはrequire('./module')
  2. ./index.jsspec/specs.jsに複製しないでください。 (そして、入力モジュールとしてsrc/app.jsが実行されないようにする)。

答えて

4

これらの回答は、プロジェクトの残りの設定方法によって異なりますが、それは良い出発点です。また、実際に動作させるには、grunt-browserifyの現在のv2ベータ版を使用する必要があります(npm install [email protected])。

1.

あなたのモジュールのためのいくつかの動的なエイリアスを作成するためにaliasMappingを使用することができます。分かりやすくするため、すべてのモジュールをsrc/modules/に移動してください。次に、コンフィギュレーションはこのようなものかもしれないaliasMapping:

options: { 
    aliasMappings: { 
    cwd: 'src', 
    src: ['modules/**/*.js'] 
    } 
} 

にかかわらず必要をやっている.jsファイルが置かれているのは、あなたがこのようにそれを必要とすることができ、あなたがsrc/modules/magic/stuff.jsにモジュールがあるとしましょう この1わからない2.

var magicStuff = require('modules/magic/stuff.js'); 

。あなたのプロジェクトの構造はspec/index.jsですが、あなたはspec/specs.jsと言います。彼らは同じファイルであるはずですか?

とにかく、重複していることは何ですか? ./index.jsspec/index.jsとは異なるエントリファイルを持っているためです。 をspecs/に含める方法を探している場合は、ゼロから構築する代わりにテストを実行する前にコピーすることができます。

+0

「spec/index.js」vs「spec/specs、js」はタイプミスです。編集された質問。答えてくれてありがとう。オリジナル(古いバージョン)がこの設定を行うようには設計されていないという真実のようです。私はもっ​​と良い質問があると思います*どのようにこのようなプロジェクトを整理する必要がありますか?多くのチュートリアルでは、プロダクションスクリプトとテストスクリプトがバンドルされていません。 testemのようなものを追加すれば、人々は混乱することはありません。これらすべてのパッケージを調和させて統合するためのメタガイドラインが必要です。 – Sukima

+1

おそらく根本的な問題は、JSエコシステムの多様性です。まだ若いです。たぶん、ある日、重複したパッケージ/ユーティリティが共存するのをやめ、そのうちの1つがXの問題を解決するためのデフォルトリソースになるでしょう。今のところ、JSについて言えば、少なくとも2/3の異なるライブラリが同じことをしています。したがって、ビルドシステムのようなものは完全に無関係で、ライブラリの可能なすべての組み合わせに対してうまく機能することは特に困難です。 –

+0

この 'aliasMappings'オプションは' grunt-browserify'に特有のものか、あるいは 'browserify'隠れオプションのラッパーですか?私は['opts.basedir'](https://github.com/substack/node-browserify#var-b--browserifyfiles-or-opts)オプションで同じ動作をしようとしていますが、運はありません。 。 – eightyfive

29

簡単な答えは:

最も簡単なのはbrowserifyのpathsオプションを使用することです。私は数ヶ月間それを大成功に使用します。 node_modules何も通常の に見つからない場合に使用するあなたが持っている場合は、再帰徒歩

をrequire.paths配列 - https://github.com/stample/gulp-browserify-react-phonegap-starter

var b = browserify('./app', {paths: ['./node_modules','./src/js']}); 

パス:私も、この機能を使用するスターターキットを作りましたsrc/js/modulePath/myModule.jsのファイルでは、require("myModule")をどこにでも書き込むことはできませんが、require("modulePath/myModule")は他のソースファイルから書き込むことができます。

廃止予定のオプション?

そうは思われません!

Browserifyモジュール解決アルゴリズムはresolution algorithm in NodeJSを反映します。 Browserifyのpathsオプションは、NodeJSの可変動作であるNODE_PATH envのミラーです。 このSOトピックのBrowserify author(substack)の主張は、NODE_PATHオプションがNodeJSで非推奨であるため、Browserifyでも非推奨であり、次のバージョンでは削除される可能性があります。

私はこの主張に同意しません。

NODE_PATHのドキュメントを参照してください。このオプションは推奨されていません。

あなたは非常に node_modulesフォルダにローカルにあなたの依存関係を配置することが奨励されています。しかし、まだsubstackの主張の方向に行い、興味深い言及があります。それらはより速く、より確実にロードされます。

this questionが2012年にメーリングリストに掲載されました。

Oliver Leics: is NODE_PATH deprecated? 
Ben Noordhuis (ex core NodeJS contributor): No. Why do you ask? 

そして何かがNodeJS解決アルゴリズムで削除されていない場合、私はそれがいつでもすぐにBrowserifyから削除されるとは思わない:)あなたはpathsオプションを使用するか

結論

公式文書のようにnode_modulesに、Browserify author recommendsのようにコードを入れてください。

個人的には、自分のコードをnode_modulesに入れたいという考えが好きではありません。単にこの全体のフォルダを自分のソース管理から外しておくだけです。私は数ヶ月間pathsオプションを使用していましたが、まったく問題はありませんでした。ビルドの速度はかなり良いです。 node_modules内のシンボリックリンクを置く

substackのソリューションは便利かもしれないが、残念ながら我々はここでのWindowsで作業する開発者を持っている...

私ははあなたがpathsオプションを使用したくない場合は、しかし、そこだと思います:他のアプリで必要となるNPMリポジトリに公開されているライブラリを開発しているとき。これらのライブラリクライアントが、あなたのlibの相対パス地獄を避けたいという理由だけで、特別なビルド設定をセットアップする必要はありません。そのアプローチは、ノードとbrowserifyにおけるモジュールシステムの廃止予定の一部であるため

別の可能なオプションは、エイリアスとopts.paths/$NODE_PATHについてここremapify

+2

ちょうどこのスレッドに出くわしました。このオプションは、現在のbrowserify/grunt-browserifyの方が優れています。 –

+0

Browserify 8.1で 'paths'を使用すると他の誰かが問題を見たことがありますか?(ブラウザのオプションに注意してください) .1?私は「モジュールが見つかりません」というメッセージを見て、8.0.1に戻ってきました。あなたの洞察に感謝します。 – Cory

6

すべての答えを使用することですが素晴らしいではありませんので、それは時に動作を停止する可能性がありどんなときも。

ネストされたnode_modulesディレクトリで効果的にコードを編成できるように、how the node_modules algorithm worksを学ぶ必要があります。

avoiding ../../../../../../..相対パスの問題をカバーするセクションがbrowserifyハンドブックにあります。あなたがrequire('yourmodule')require('app/yourmodule')がお好みかに依存することができるようnode_modules/またはnode_modules/appにあなたの内部のモジュラーコードを入れて

  • :のように要約することができます。
  • Windows以外のプラットフォーム用に開発している場合は、シンボリックリンクを使用することができます。

opts.path/$NODE_PATHを使用しないでください。それはあなたのプロジェクトを作る:

  • は、暗黙のうちに、アレイ・パスが推奨されていませんので、ノードおよびモジュールシステムの変化に脆弱なブラウザ
  • の両方で仕事をすることが難しく
  • を設定する非自明な構成や環境によって異なりますノードとブラウザで
+0

'opts.path'が非難された理由を知っていますか?私は廃止されたソリューションを使用するのは好きではありませんが、この廃止予定のオプションは 'node_modules'にコードを入れるよりはるかに便利だと思います。あなたはそれが非難された理由を知っていますか?どんなgithubの問題?私は見つけられません –

+0

ところで、公式の文書(http://nodejs.org/api/modules.html)で読むことができます: 'モジュールをREPLノードで利用できるようにするには、役に立つかもしれません$ NODE_PATH環境変数に/ usr/lib/node_modulesフォルダも追加します。 node_modulesフォルダを使用したモジュールルックアップはすべて相対的なものであり、require()の呼び出しを行うファイルの実際のパスに基づいているので、パッケージ自体はどこにでも置くことができます。 ''公式ドキュメントを参照して、これを反映していません。 –

+0

これで、あなたがここで何を言っているのかを知ることができました:http://nodejs.org/api/all.html#all_loading_from_the_global_folders 'これは主に歴史的な理由によるものです。依存関係をnode_modulesフォルダにローカルに配置することを強くお勧めします。彼らはより速く、より確実にロードされます。それは推奨事項ですが、実際にはこの機能は推奨されなくなり、削除される可能性はありません。このMLディスカッションでも推奨されていません:https://groups.google.com/forum/#!topic/nodejs/EENwg8GAJd8 –

1

Sebastien Lorberが指摘しているように、パイプを通してブラウザを呼び出す際のパスを設定することが最善の方法だと思います。

しかしbrowserifyの最新バージョン、(この瞬間のように、それが[email protected]ある)パス変数を格納Browserifyは、そのプロセスに使用されますのみパスを持ちます。だから、パス変数を設定すると、あなたが言うことができる限り、ノードのグローバルフォルダを除外します。結果として、次のようなGulpタスクが必要になります。

gulp.task('reactBuild', function() { 
    return gulp.src(newThemeJSX) 
    .pipe(browserify({ 
     debug: true, 
     extensions: ['.jsx', '.js', '.json'], 
     transform: [reactify], 
     paths: ['../base_folder/node_modules', '/usr/lib/node_modules'] 
    })) 
    .pipe(gulp.dest(newThemeBuilt)) 
    .on('error', function(error) { 
     console.log(error); 
    }); 
}); 
関連する問題