node.jsを絶対に必要とする方法は?(親戚の代わりに)


234

現在のモジュールに相対的ではなく、常にプロジェクトのルートでファイルを要求したいと思います。

たとえば、https://github.com/visionmedia/express/blob/2820f2227de0229c5d7f28009aa432f9f3a7b5f9/examples/downloads/app.jsの 6行目を見ると、

express = require('../../')

それは本当に悪いIMOです。すべての例を1レベルだけルートに近づけたいと想像してください。30を超える例を何度も更新する必要があるため、それは不可能です。これに:

express = require('../')

私の解決策はルートベースの特別なケースを持つことです:文字列が$で始まる場合、それはプロジェクトのルートフォルダに関連しています。

助けてくれてありがとう

アップデート2

現在、require.jsを使用しています。これにより、一方向で記述でき、クライアントとサーバーの両方で機能します。Require.jsでは、カスタムパスを作成することもできます。

アップデート3

ここでwebpack + gulpに移動し、サーバー側でモジュールを処理するためにEnhanced-Requireを使用します。ここで理論的根拠を参照してくださいhttp : //hackhat.com/p/110/module-loader-webpack-vs-requirejs-vs-browserify/


明示的なルートパス定数/変数を使用することを決定した場合、この答えはそのために機能します。ソリューションは、小さなgithubモジュールを使用してルートパスを決定します。
15年

回答:


162

そして何について:

var myModule = require.main.require('./path/to/module');

メインのjsファイルから必要であるかのようにファイルを必要とするため、メインのjsファイルがプロジェクトのルートにある限り、うまく機能します。


悪い考えではありません(必要に応じて他のメソッドを定義して、require.mainモジュールでアプリを何らかの方法で再マッピングできます。require.main.req( 'client / someMod')を実行できると思います。いい考えですが、私の現在のrequirejsよりも詳細にしてください。また、変更は瞬時ではなく、変更を見逃すため、browserifyも嫌いなので、価値がないと思います(コードはbrowserとnode.jsの両方で実行する必要があるためです)
Totty.js

4
冗長すぎる場合は、.bind()を使用してください。var rootReq = require.bind(require.main); rootReq( './path/to/module');
cronvel 2014年

はい、これはクライアントサイドでbrowserifyを使いたい人にとって便利です。私にとってはもう必要はありませんが、とにかくあなたの答えに感謝します(:
Totty.js

6
メインがプロジェクトの最前線にいる場合:)
Alexander Mills

12
このソリューションは、Mochaテストなどの単体テストでカバーされているコードの場合は機能しません
alx lark

129

Browserifyハンドブックには、非常に興味深いセクションがあります

../../../../../../ ..の回避

アプリケーションのすべてが適切にパブリックnpmに属しているわけではなく、プライベートnpmまたはgitリポジトリをセットアップするオーバーヘッドは、多くの場合、依然としてかなり大きいです。ここでは、../../../../../../../相対パスの問題を回避するためのいくつかのアプローチを示し ます。

node_modules

npmからサードパーティのモジュールをチェックインしないと内部モジュールをチェックインする方法が明確でないため、アプリケーション固有のモジュールをnode_modulesに入れることに反対する人がいます。

答えは簡単です!.gitignore無視するファイルがある場合node_modules

node_modules

!内部アプリケーションモジュールごとに例外を追加できます。

node_modules/*
!node_modules/foo
!node_modules/bar

あなたがすることはできませんのでご注意ください除外を解除サブディレクトリ、親がすでに無視されている場合。したがって、を無視する代わりに、トリックを使用して 内部のnode_modulesすべてのディレクトリを無視する必要があります。その後、例外を追加できます。 node_modulesnode_modules/*

今、どこでも、あなたのアプリケーションでは次のことができるようになりますrequire('foo') か、require('bar')非常に大規模で脆弱な相対パスを有しない。

多くのモジュールがあり、それらをnpmによってインストールされたサードパーティのモジュールからより分離したい場合は、次のnode_modulesようなディレクトリの下にそれらをすべて置くことができますnode_modules/app

node_modules/app/foo
node_modules/app/bar

これ で、アプリケーションのどこからでも、require('app/foo')またはrequire('app/bar')どこからでもアクセスできるようになります。

.gitignore、次の例外を追加するだけですnode_modules/app

node_modules/*
!node_modules/app

アプリケーションのトランスフォームがpackage.jsonで構成されている場合、トランスフォームはモジュールの境界を越えて適用されないため、独自のトランスフォームフィールドを使用して、node_modules/fooまたはnode_modules/app/fooコンポーネントディレクトリに個別のpackage.jsonを作成する必要があります。これにより、アプリケーションの構成変更に対するモジュールの堅牢性が向上し、アプリケーションの外部でパッケージを個別に再利用しやすくなります。

シンボリックリンク

シンボリックリンクを作成でき、ウィンドウをサポートする必要がないアプリケーションで作業している場合のもう1つの便利なトリックは、lib/ またはapp/フォルダーをにシンボリックリンクすることnode_modulesです。プロジェクトのルートから、以下を実行します。

ln -s ../lib node_modules/app

そして、プロジェクトのどこからでも、getをlib/実行require('app/foo.js')することにより、ファイルを要求できるようになりlib/foo.jsます。

カスタムパス

$NODE_PATH 環境変数の使用について話したりopts.paths、nodeおよびbrowserifyのディレクトリを追加してモジュールを検索したりする場所が見られるかもしれません。

他のほとんどのプラットフォームとは異なり、パススタイルのシェルスタイルの配列をで$NODE_PATH使用することは、node_modulesディレクトリを効果的に使用することと比較して、ノードではあまり有利ではありません。

これは、アプリケーションがランタイム環境の構成とより密接に結合されているため、可動部分が多くなり、環境が正しく設定されている場合にのみアプリケーションが機能するためです。

nodeとbrowserifyはどちらもサポートしますが、の使用はお勧めしません $NODE_PATH


17
それをnode_modulesフォルダに入れることの唯一の欠点は、それが(rm -rf node_modules)フォルダをnukeするのを難しくすることです
Michael

13
@Michaelそれほど難しくはありません:git clean -dx node_modules
Peter Wilkinson

3
それとも、忘れてしまった場合のgit clean構文を、1が常にできるrm -rf node_modules && git checkout node_modules-に必ずgit stash場合に何らかの変更があるnode_modulesサブディレクトリが。
derenio

1
私はnode_modulesを使用するというアイデアが好きですが、ソースコードをどれだけ揮発性であるかを考慮して保存するのは好きではありません。分離されたモジュールを公開して、元のプロジェクトの依存関係として保存する方が理にかなっているのではないでしょうか。これは、node_modulesディレクトリの変動性に対する明確なソリューションを提供し、git、シンボリックリンク、または$ NODE_PATHソリューションに依存するのではなく、npmにのみ依存します。
Kevin Koshiol 16年

1
NODE_PATHは進むべき道のように見えます。「アプリケーションは、環境が正しく設定されている場合にのみ機能します」これは常に当てはまります。すべてのファイルですべてのインポートを変更するよりも、環境設定を(通常は1つのファイルで)取得する方が簡単ではないですか。
CpILL 2017

73

node_modules共有コード用の新しいフォルダーを作成し、ノードにそれを実行させて、それが最善を尽くすことを要求します。

例えば:

- node_modules // => these are loaded from your package.json
- app
  - node_modules // => add node-style modules
    - helper.js
  - models
    - user
    - car
- package.json
- .gitignore

たとえば、あなたがしている場合、car/index.jsすることができますrequire('helper')し、ノードがそれを見つけるでしょう!

node_modulesの仕組み

ノードには、競合するプラットフォーム間でユニークなモジュールを解決するための巧妙なアルゴリズムがあります。

require('./foo.js')からの場合/beep/boop/bar.js、ノードはで検索./foo.js/beep/boop/foo.jsます。./またはで始まるパスは、../を呼び出すファイルに対して常にローカルrequire()です。

ただし、require('xyz')from などの非相対名が必要な場合/beep/boop/foo.js、ノードはこれらのパスを順番に検索し、最初の一致で停止し、何も見つからない場合はエラーを発生させます。

/beep/boop/node_modules/xyz
/beep/node_modules/xyz
/node_modules/xyz

xyz存在するディレクトリごとに、ノードは最初にa xyz/package.jsonを探して"main"フィールドが存在するかどうかを確認します。この"main"フィールドはrequire()、ディレクトリパスの場合にどのファイルが担当するかを定義します。

たとえば/beep/node_modules/xyz、が最初に一致し、次のようになっているとし/beep/node_modules/xyz/package.jsonます。

{
  "name": "xyz",
  "version": "1.2.3",
  "main": "lib/abc.js"
}

からのエクスポート/beep/node_modules/xyz/lib/abc.jsはによって返され require('xyz')ます。

フィールドがない場合、package.jsonまたは"main"フィールドがない場合は、以下index.jsが想定されます。

/beep/node_modules/xyz/index.js

2
モジュールをロードするときの動作のすばらしい説明
15

2
これは非常にエレガントなソリューションであり、上記の回答のすべての問題を回避します。答えを考える必要があります、imho。
ロドリコ

38

大きな絵

「本当に悪い」ようですが、時間をかけてください。それは実際、本当に良いです。明示的なrequire()は、プロジェクトのライフサイクル中の新鮮な空気の息吹のような、完全な透明性と理解の容易さを提供します。

このように考えてください。あなたは例を読んでいて、つま先をNode.jsに浸していて、「本当に悪いIMO」であると判断しました。あなたはNode.jsコミュニティの2番目の推測リーダーであり、Node.jsアプリケーションの作成と保守に誰よりも多くの時間を費やしている人々です。著者がそのような新人の間違いをした可能性は何ですか?(そして、RubyとPythonのバックグラウンドから、私は最初は災害のように思えます。)

Node.jsを取り巻く誇大宣伝と反宣伝がたくさんあります。しかし、ほこりが落ち着くと、明示的なモジュールと「ローカルファースト」パッケージが採用の主な推進力になったことを認めます。

一般的なケース

もちろん、node_modules現在のディレクトリから、次に親、次に祖父母、曾祖父母などが検索されます。したがって、インストールしたパッケージはすでにこの方法で動作しています。通常require("express")、プロジェクトのどこからでもアクセスでき、問題なく機能します。

プロジェクトのルートから一般的なファイルをロードしている場合(おそらく、それらは一般的なユーティリティ関数であるため)、それはパッケージを作成するときの大きな手がかりです。パッケージは非常に単純です:にあなたのファイルを移動node_modules/して置くpackage.json が。出来上がり!その名前空間のすべてにプロジェクト全体からアクセスできます。パッケージは、コードをグローバル名前空間に入れる正しい方法です。

その他の回避策

私は個人的にこれらのテクニックを使用しませんが、彼らはあなたの質問に答えます、そしてもちろんあなたは私よりあなた自身の状況をよく知っています。

$NODE_PATHプロジェクトのルートに設定できます。すると、そのディレクトリが検索されますrequire()

次に、すべての例から共通のローカルファイルを侵害して要求することができます。その共通ファイルは、祖父母ディレクトリーにある真のファイルを単に再エクスポートします。

examples / downloads / app.js(および他の多くの

var express = require('./express')

examples / downloads / express.js

module.exports = require('../../')

これらのファイルを再配置すると、最悪の場合、1つのshimモジュールが修正されます。


14
Node.jsの人たちは、理由のために相対的な要求を選択したに違いないことに同意します。あなたの答えからも、私はその利点を見ることができません。それはまだ私にとって「悪い」と感じています;)
アダムシュミデグ2013

21
「あなたはNode.jsコミュニティの2番目の推測のリーダーです」-同じリーダーがフューチャー/プロミスの代わりにコールバックを使用することを決定しました。私のnodejsコンサルティングの大部分は、言われた「リーダー」を罵倒し、人々をJVMに移すように説得することを含みます。nodejsを数か月使用すると、はるかに簡単になります:)
David Sergey

8
@ nirth、JVMに移動しますか?神のために、なぜですか?
Ivancho 2014

31
「あなたはNode.jsコミュニティの2番目に推測的なリーダーです」この考えを刺激するような口調は避けてください。
atlex2

15
くそっ、彼は2番目の推測ノードリーダーです。それが業界の進歩です。ノードの連中がスレッドベースの同時実行モデルを支持するリーダーを2番目に推測しなかった場合、ノードはありません。
d512

20

node-rfrを見てください

それはこれと同じくらい簡単です:

var rfr = require('rfr');
var myModule = rfr('projectSubDir/myModule');

2行目はvar myModule = rfr( '/ projectSubDir / myModule');
シコルスキー2014年

1
ドキュメントから:var module2 = rfr( 'lib / module2'); //先頭のスラッシュは省略できます。
igelineau 2015年

私は試してみましたが、rfrはノードで実行しても問題ありませんが、VS Codeでのコードナビゲーションを壊します... VSでオートコンプリートを使用できるようにするために、回避策を見つけることができませんでした...
Alex Mantaut

13

あなたが使用している場合は、糸の代わりに、NPMをあなたが使用することができるワークスペースを

servicesもっと簡単に必要なフォルダがあるとします。

.
├── app.js
├── node_modules
├── test
├── services
   ├── foo
   └── bar
└── package.json

糸のワークスペースを作成するには、package.json内にファイルを作成しますservices folder

{
  "name": "myservices",
  "version": "1.0.0"
}

メインのpackage.jsonに以下を追加します:

"private": true,
"workspaces": ["myservices"]

yarn installプロジェクトのルートから実行します。

次に、コードの任意の場所で、次のことができます。

const { myFunc } = require('myservices/foo')

次のようなものの代わりに:

const { myFunc } = require('../../../../../../services/foo')

6
おそらく、これがnpmではなく、yarnに対してのみ機能することを明確にするという考えですか?私はそれがおそらくnpmでも機能すると考えたので、代わりにヤーンを使用するまで、何が悪いのか疑問に思って少し時間を費やしました。愚かな仮定だったかもしれませんが、おそらく私だけではありません。
ArneHugo

2
明確にするために少し編集しました。混乱させて申し訳ありません。
cyberwombat

12

私見、最も簡単な方法は、GLOBALオブジェクトの一部として独自の関数を定義することです。projRequire.js次の内容でプロジェクトのルートに作成します。

var projectDir = __dirname;

module.exports = GLOBAL.projRequire = function(module) {
  return require(projectDir + module);
}

requireプロジェクト固有のモジュールを使用する前のメインファイル:

// init projRequire
require('./projRequire');

その後、私にとっては次のように動作します:

// main file
projRequire('/lib/lol');

// index.js at projectDir/lib/lol/index.js
console.log('Ok');


@Totty、私は別の解決策を考え出しましたが、コメントで説明したケースでうまくいく可能性があります。説明になるtl;drので、テストプロジェクトの構造を図で示します。


まあ、これまでこれがそれを行うための最良の方法のようです。私はそうします:GLOBAL.requires = require( 'r')。r; 私のindex.jsファイルで。しかし、誓約のテストに問題があります。それらはindex.jsを実行しないため、requiresSが未定義であるため、テストは失敗します。とにかく今のところ、GLOBAL.requires = require( 'r')。r;を追加できます。すべてのテストの上部にあります。より良いアイデアはありますか?github.com/totty90/production01_server/commit/...
Totty.js


この問題は、「pathes-test / node_modules / other.js」にいて、「pathes-test / node_modules / some.js」が必要な場合に発生します。require( "prj / some")の代わりにrequire( './ some')をすべきです。そして、このようにして私のアプリはすべてnode_modulesディレクトリにありますか?
Totty.js

@Totty、必要な問題はないprj/someからprj/other(ちょうどテストrequire('prj/some')。アプリの一般的なモジュールはすべてそこにアクセスできます(データベースレイヤーなど)。たとえば、あなたのいる場所に違いはありませんlib。それが適しているかどうか試してみてください。
アレクセイザブロドスキー

ええ、私はそれを更新しました:github.com/totty90/production01_server/tree/master/node_modules/…それはうまくいきました。しかし、node_modulesを使用せずにすべてのファイルを1レベル上げることができますか?
Totty.js

12

process.cwd()は自分のプロジェクトで使用しています。例えば:

var Foo = require(process.cwd() + '/common/foo.js');

requireまだこの問題に遭遇していませんが、これは絶対パスになることに注意する価値があります。


1
CWDは、アプリケーションが保存されているディレクトリと同じである必要がないため、これは悪い考えです。
ジウォペン

11

この問題についてのよい議論はここにあります

私は同じアーキテクチャの問題に遭遇しました。アプリケーションなしで、より多くの組織と内部名前空間を提供する方法が必要です。

  • アプリケーションモジュールを外部の依存関係と混合したり、アプリケーション固有のコードのプライベートnpmリポジトリを使用したりする
  • 相対要件を使用すると、リファクタリングと理解が難しくなります
  • シンボリックリンクを使用するか、ノードのパスを変更すると、ソースの場所がわかりにくくなり、ソース管理がうまく機能しない

結局、ディレクトリではなくファイルの命名規則を使用してコードを整理することにしました。構造は次のようになります。

  • npm-shrinkwrap.json
  • package.json
  • node_modules
    • ...
  • src
    • app.js
    • app.config.js
    • app.models.bar.js
    • app.models.foo.js
    • app.web.js
    • app.web.routes.js
    • ...

次にコードで:

var app_config = require('./app.config');
var app_models_foo = require('./app.models.foo');

あるいは単に

var config = require('./app.config');
var foo = require('./app.models.foo');

そして外部依存関係はいつものようにnode_modulesから利用可能です:

var express = require('express');

このようにして、すべてのアプリケーションコードは階層的にモジュール化され、アプリケーションルートに関連する他のすべてのコードで使用できます。

主な欠点はもちろん、ファイルブラウザでは、ツリーが実際にディレクトリに編成されているかのようにツリーを展開/折りたたむことができないことです。しかし、すべてのコードがどこから来ているのかが非常に明確であり、「マジック」を使用しないことが好きです。


リンクした要旨から、ソリューション#7「ラッパー」は非常にシンプルで便利です。
Pier-Luc Gendreau、2014

ファイルを別の「フォルダ」に「移動」すると名前が変更され、ファイルを移動するよりも簡単です。さらに、プロジェクトでの30時間の作業の後に、ほとんどすべてのアプリツリーがとにかく展開されていることに気づく傾向があります。1レベルのフォルダースペースを追加すると、大きなコードベースを管理しやすくなり、../x/xすでに読み取り可能な量が多くなりすぎないようにすることができます。
スキー

nodejsの明らかな欠如を克服するために、スラッシュの代わりにドットを使用して、フォルダーを再発明しています。
Simone Gianni

9

プロジェクトのルートが現在の作業ディレクトリであると仮定すると、これは機能するはずです。

// require built-in path module
path = require('path');

// require file relative to current working directory
config = require( path.resolve('.','config.js') );

config = require('./config.js');も有効です。
cespon

7
@cesponいいえ、必要なファイルに関連するだけです。
プロトメタ2015

8

私はこれらの解決策の多くを試しました。私はこれをメインファイル(たとえば、index.js)の先頭に追加しました。

process.env.NODE_PATH = __dirname;
require('module').Module._initPaths();

これにより、スクリプトのロード時にプロジェクトルートがNODE_PATHに追加されます。を使用すると、などのプロジェクトルートからの相対パスを参照することで、プロジェクト内の任意のファイルを要求できますvar User = require('models/user')。このソリューションは、プロジェクトで他の何かを実行する前に、プロジェクトルートでメインスクリプトを実行している限り機能します。


8

答えのいくつかは、パッケージとしてnode_moduleにコードを追加するのが最善の方法であると述べています。私は同意し、おそらく../../../in require を失う最善の方法ですが、実際にそうする方法はありません。

バージョン2.0.0から、ローカルファイルからパッケージをインストールできます。つまり、必要なすべてのパッケージを含むフォルダーをルートに作成できます。

-modules
 --foo
 --bar 
-app.js
-package.json

したがって、package.jsonでは、次のように外部サーバーを公開したり使用したりせずにmodules(またはfooand bar)をパッケージとして追加できます。

{
  "name": "baz",
  "dependencies": {
    "bar": "file: ./modules/bar",
    "foo": "file: ./modules/foo"
  }
}

その後、を実行npm installするとvar foo = require("foo")、他のすべてのパッケージと同様に、を使用してコードにアクセスできます。

詳細はここにあります:

https://docs.npmjs.com/files/package.json#local-paths

そしてここでパッケージを作成する方法:

https://docs.npmjs.com/getting-started/creating-node-modules


1
「この機能は、ローカルのオフライン開発や、外部サーバーにアクセスしたくない場所にnpmのインストールを必要とするテストの作成に役立ちますが、パッケージを公開レジストリに公開するときに使用しないでください。」
ライアン・スミス

7

私が作成したモジュール、Undotを使用できます。それは高度なものではなく、単なるヘルパーなので、単純にそれらの地獄を回避することができます。

例:

var undot = require('undot');
var User = undot('models/user');
var config = undot('config');
var test = undot('test/api/user/auth');

6

app.jsで次のように定義できます。

requireFromRoot = (function(root) {
    return function(resource) {
        return require(root+"/"+resource);
    }
})(__dirname);

そして、ルートから何かを要求したいときはいつでも、どこにいても、バニラrequireの代わりにrequireFromRootを使用するだけです。これまでのところ、私にはかなりうまくいきます。


ありがとう!これはかなりスマートで簡単だと思います。
ライアン

私が罪を犯したので、父を許してください。これをES6に移植して、次の情報を得ましたrequireFromRoot = ((root) => (resource) => require(`${root}/${resource}`))(__dirname);。ソリューションが大好きですが、本当に__dirnameをそのようにバインドする必要がありますか?
Nuck

1
私の記憶はこれで少しかすんでいますが、__ dirnameはそれがどのファイル内で使用されているかによって値が変わると思います。関数が1か所で定義されているが複数の場所で使用されているため、このバインドがなくても値は一定のままである可​​能性がありますが、実際にそうであることを確認するためにそれを行いました。
user1417684 2014

これはずっと前に行われたものであり、envsのテストなどに苦労します。オーバーヘッドの価値はありません。ランダムな新しいグローバルは、新しい人々を不確かにしますbla bla
デンビンスキー2017年

そして、あなたはrequireこの機能をどのようにしていますか?
Darko Maksimovic

5

これが私が6か月以上行っている実際の方法です。私はnode_modulesという名前のフォルダーをプロジェクトのルートフォルダーとして使用します。このようにして、絶対必須と呼ばれるすべての場所から常にそのフォルダーを探します。

  • node_modules
    • 私のプロジェクト
      • index.js require( "./ someFolder / hey.js")の代わりにrequire( "myProject / someFolder / hey.js")できます
      • hey.jsを含むsomeFolder

これは、フォルダにネストされている場合により便利です。絶対的な方法で設定されている場合、ファイルの場所を変更する作業ははるかに少なくなります。私は、アプリ全体で2つの相対的な要件のみを使用します。


4
ローカル(プロジェクト)をに追加することを除いて、同様のアプローチを使用node_modules/src/node_modulesベンダーが物事を分離しておくようにします。だから私は/src/node_modulesローカルコードと/node_modulesベンダーのために持っています。
MariusBalčytis2013年

33
IMHO node_modulesフォルダーは、node_modules専用です。プロジェクト全体をそのフォルダー内に置くことはお勧めできません。
McSas 2013年

2
@McSas上記と同じ効果を得るための代替案として何を提案しますか?
spieglio 2014年

3
@cspiegl NODE_PATH環境変数を使用できます
Christopher Tarquini

5

これを実現する最も簡単な方法は、アプリの起動時にシンボリックリンクを作成するnode_modules/appことです(またはそれを呼び出すものは何でも)../app。その後、単に呼び出すことができますrequire("app/my/module")。シンボリックリンクは、すべての主要なプラットフォームで使用できます。

ただし、それでも、npmを介してインストールされる、保守しやすい小さなモジュールにデータを分割する必要があります。git-urlを使用してプライベートモジュールをインストールすることもできるため、1つのモノリシックapp-directoryを作成する必要はありません。


Windowsでのサポートには、ノードとOSに関するより深い知識が必要です。オープンソースプロジェクトの広範な使用を制限する可能性があります。
Steven Vachon 2014

一般に、私はこのパターンをライブラリ(ほとんどのオープンソースプロジェクトがそうである)に使用しません。ただし、これらのシンボリックリンクをnpmビルドフックで作成することができるため、ユーザーが必要とする詳細な知識はありません。
Johannes Ewald 2014

もちろん、WindowsのNode.jsはデフォルトでシンボリックリンクをサポートしていません。
Steven Vachon 2014年

4

独自のプロジェクトでは、ルートディレクトリで使用されている.jsファイルを変更し、そのパスをprocess.env変数のプロパティに追加できます。例えば:

// in index.js
process.env.root = __dirname;

その後、どこからでもアクセスできます。

// in app.js
express = require(process.env.root);

4

別の答え:

このフォルダ構造を想像してください:

  • node_modules
    • ロダッシュ
  • src
    • サブディレクトリ
      • foo.js
      • bar.js
    • main.js
  • テスト

    • test.js

次にtest.jsで、次のようなファイルを要求する必要があります。

const foo = require("../src/subdir/foo");
const bar = require("../src/subdir/bar");
const main = require("../src/main");
const _ = require("lodash");

そしてmain.jsで

const foo = require("./subdir/foo");
const bar = require("./subdir/bar");
const _ = require("lodash");

これで、これでbabelbabel-plugin-module-resolverを使用できます。2つのルートフォルダーを構成するbabelrcファイル:

{
    "plugins": [
        ["module-resolver", {
            "root": ["./src", "./src/subdir"]
        }]
    ]
}

これで、テストsrcで同じ方法でファイルを要求できます。

const foo = require("foo");
const bar = require("bar");
const main = require("main");
const _ = require("lodash");

es6モジュール構文を使用する場合:

{
    "plugins": [
        ["module-resolver", {
            "root": ["./src", "./src/subdir"]
        }],
        "transform-es2015-modules-commonjs"
    ]
}

次に、テストsrcに次のようにファイルをインポートします。

import foo from "foo"
import bar from "bar"
import _ from "lodash"


3

examplesディレクトリにnode_modulesプロジェクトのルートへのシンボリックリンクを含むを含めることができなかったproject -> ../../ため、例を使用できるようになりましたrequire('project')が、これによりマッピングは削除されませんが、ソースではrequire('project')なく、require('../../')ます。

私はこれをテストしましたが、v0.6.18でも動作します。

projectディレクトリのリスト:

$ ls -lR project
project:
drwxr-xr-x 3 user user 4096 2012-06-02 03:51 examples
-rw-r--r-- 1 user user   49 2012-06-02 03:51 index.js

project/examples:
drwxr-xr-x 2 user user 4096 2012-06-02 03:50 node_modules
-rw-r--r-- 1 user user   20 2012-06-02 03:51 test.js

project/examples/node_modules:
lrwxrwxrwx 1 user user 6 2012-06-02 03:50 project -> ../../

の内容はindex.jsexportsオブジェクトのプロパティに値を割り当て、console.log必要であることを示すメッセージを表示して呼び出します。の内容はtest.jsですrequire('project')


テストのソースコードを見せてもらえますか?まあ、そして私がこのように( 'project.a')を要求しなければならないならそれはうまくいくでしょう?
Totty.js

どういう意味require('project.a')ですか?ということもあると思いますがrequire('project/a')require('project').a可能ですか?
Dan D.

しかし、あなたの例では、requireメソッドを必要とするモジュールがある各フォルダーにこれらのフォルダーを作成する必要があります。とにかく、フォルダに応じて「../」の時間に注意する必要があります。
Totty.js

実際、リンクはnode_modulesファイルの両方の最も近い親のディレクトリにある必要があるだけで、リンクは両方で同じになります。nodejs.org/api/…を
Dan D.

そして、その場所から相対的です。例:project/node_modules/project -> ../
Dan D.

2

誰かがこの問題を回避するためのさらに別の方法を探しているなら、ここに私自身の努力への貢献があります:

https://www.npmjs.com/package/use-import

基本的な考え方:プロジェクトのルートでJSONファイルを作成し、ファイルパスを省略名にマッピングします(またはuse-automapperで取得してください)。次に、それらの名前を使用してファイル/モジュールを要求できます。そのようです:

var use = require('use-import');
var MyClass = use('MyClass');

だからそれがあります。


2

私がしたいのは、このためにnode_moduleディレクトリからノードをロードする方法を活用することです。

モジュール「もの」をロードしようとすると、次のようなことをします

require('thing');

次に、ノードは「node_module」ディレクトリで「thing」ディレクトリを探します。

通常、node_moduleはプロジェクトのルートにあるため、この一貫性を活用できます。(node_moduleがルートにない場合は、他にも自己誘発型の頭痛の種があります。)

ディレクトリに移動して、そのディレクトリから戻ると、ノードプロジェクトのルートへの一貫したパスを取得できます。

require('thing/../../');

次に、/ happyディレクトリにアクセスする場合は、これを行います。

require('thing/../../happy');

かなりハッキーですが、node_modulesのロード方法の機能が変更されると、対処する必要のある問題が大きくなると思います。この動作は一貫している必要があります。

明確にするために、モジュールの名前は関係ないので、これを行います。

require('root/../../happy');

私は最近、angular2に使用しました。ルートからサービスをロードしたい。

import {MyService} from 'root/../../app/services/http/my.service';

Angular参照については、標準のCLIアプリケーションを使用して、単純にインポートsrc/app/my.serviceできます。また、typescriptファイルに非相対インポートを使用するようにVSCを構成することもできます。
プロッピー2018

2

グローバル変数を導入したり、ノードのデフォルトをオーバーライドしたりせずに、プロジェクトルートからの相対パスでパッケージを要求できるようにする、この小さなパッケージを作成しました

https://github.com/Gaafar/pkg-require

それはこのように動作します

// create an instance that will find the nearest parent dir containing package.json from your __dirname
const pkgRequire = require('pkg-require')(__dirname);

// require a file relative to the your package.json directory 
const foo = pkgRequire('foo/foo')

// get the absolute path for a file
const absolutePathToFoo = pkgRequire.resolve('foo/foo')

// get the absolute path to your root directory
const packageRootPath = pkgRequire.root()

メインプロジェクトにプライベートパッケージがある場合がありますが、このスクリプトはそれで壊れます。それに加えて、webpackで正常に動作するかどうかはわかりません(私がnode.jsでwebpackを使用している場合)
Totty.js

パッケージファイルを含むディレクトリをネストしている場合、各ディレクトリはパッケージ内のファイルのみを要求できます。それはあなたが望む行動ではありませんか?私はwebpackでテストしていません。
gafi

これは単純なプロジェクトで完全に機能し、他のどの回答よりもはるかに簡単です。
byxor 2017

2

Paolo MorettiとBrowserify からのすばらしい回答をフォローアップしたいだけです。トランスパイラー(例:babel、typescript)を使用していて、およびのようなソースコードとトランスパイルコード用に別々のフォルダーがある場合、次のようにソリューションのバリエーションを使用できます。src/dist/

node_modules

次のディレクトリ構造で:

app
  node_modules
    ... // normal npm dependencies for app
  src
    node_modules
      app
        ... // source code
  dist
    node_modules
      app
        ... // transpiled code

次に、babelなどにsrcディレクトリをdistディレクトリにトランスパイルさせます。

シンボリックリンク

シンボリックリンクを使用して、ネストのいくつかのレベルを取り除くことができます。

app
  node_modules
    ... // normal npm dependencies for app
  src
    node_modules
      app // symlinks to '..'
    ... // source code
  dist
    node_modules
      app // symlinks to '..'
    ... // transpiled code

babel --copy-filesに関する警告--copy-filesフラグはbabelシンボリックリンクをうまく処理しません。それは..シンボリックリンクにナビゲートし続け、無限にファイルを繰り返し見るかもしれません。回避策は、次のディレクトリ構造を使用することです。

app
  node_modules
    app // symlink to '../src'
    ... // normal npm dependencies for app
  src
    ... // source code
  dist
    node_modules
      app // symlinks to '..'
    ... // transpiled code

このようにして、下のコードsrcはにapp解決されますsrcが、バベルはシンボリックリンクを表示しなくなります。


おかげで、私はこの魔法を行うことをお勧めしません。最初にすべてのインポートが失われます。それらはIDEによって計算されません。フロータイプのような他のツールを使用する場合も、正しく機能しません。
Totty.js 2017年

私の場合、実際にはフローが機能しているようですが、ソリューションは標準のノードモジュール解決モデルとシンボリックリンクに依存しているため、驚くことではありません。したがって、flowなどのツールが理解することは、実際には魔法ではありません。しかし、IDEは異なります。
user716468 2017年

2

私はあらゆるレベルのファイルを必要とするまったく同じ単純さを探していましたが、module-aliasを見つけました。

インストールするだけです:

npm i --save module-alias

package.jsonファイルを開きます。ここで、パスのエイリアスを追加できます。たとえば、

"_moduleAliases": {
 "@root"      : ".", // Application's root
 "@deep"      : "src/some/very/deep/directory/or/file",
 "@my_module" : "lib/some-file.js",
 "something"  : "src/foo", // Or without @. Actually, it could be any string
}

そして単にあなたのエイリアスを使う:

require('module-alias/register')
const deep = require('@deep')
const module = require('something')


1

この問題に取り組むための新しい方法を試そうとしています。

springやguiceなどの他の既知のプロジェクトの例を取り上げて、「require」ステートメントをすべて含む「context」オブジェクトを定義します。

このオブジェクトは、他のすべてのモジュールに渡されて使用されます。

例えば

var context = {}

context.module1 = require("./module1")( { "context" : context } )
context.module2 = require("./module2")( { "context" : context } )

これには、各モジュールをoptsを受け取る関数として記述する必要があります。これは、いずれにしてもベストプラクティスと見なされます。

module.exports = function(context){ ... }

そして、あなたはものを必要とする代わりにコンテキストを参照します。

var module1Ref = context.moduel1;

必要に応じて、ループを簡単に記述してrequireステートメントを実行できます

var context = {};
var beans = {"module1" : "./module1","module2" : "./module2" }; 
for ( var i in beans ){
    if ( beans.hasOwnProperty(i)){
         context[i] = require(beans[i])(context);
    }
};

これにより、モック(テスト)を行うときに作業が楽になり、コードをパッケージとして再利用できるようにしながら、途中で問題が解決されます。

Bean宣言を分離して、コンテキスト初期化コードを再利用することもできます。たとえば、main.jsファイルは次のようになります

var beans = { ... }; // like before
var context = require("context")(beans); // this example assumes context is a node_module since it is reused.. 

この方法は外部ライブラリにも適用されます。外部ライブラリが必要になるたびに名前をハードコードする必要はありません。ただし、エクスポートはコンテキストを期待する関数ではないため、特別な処理が必要になります。

後で、Beanを関数として定義することもできrequireます。これにより、環境に応じてさまざまなモジュールを使用できるようになりますが、このスレッドのスコープ外です。


1

同じ問題で問題が発生したため、includeというパッケージを作成しました。

package.jsonファイルを見つけることでプロジェクトのルートフォルダーを特定するハンドルを含め、相対パスをすべて混乱させることなく、ネイティブrequire()にパス引数を渡します。require()の代わりではなく、パッケージ化されていない/サードパーティ以外のファイルまたはライブラリの処理を要求するためのツールだと思います。何かのようなもの

var async = require('async'),
    foo   = include('lib/path/to/foo')

これがお役に立てば幸いです。


1

アプリのエントリポイントjsファイル(つまり、実際に「ノード」を実行するファイル)がプロジェクトのルートディレクトリにある場合、これはrootpath npm moduleを使用して非常に簡単に行うことができます。単にそれを介してそれをインストールします

npm install --save rootpath

...次に、エントリポイントのjsファイルの最上部に、以下を追加します。

require('rootpath')();

その時点以降、すべての必要な呼び出しはプロジェクトルートに相対的にrequire('../../../config/debugging/log'); なりrequire('config/debugging/log');ます。たとえば、次のようになります(configフォルダーがプロジェクトルートにある場合)。


1

簡単な行で、uは自分のフォルダをモジュールとして呼び出すことができます:

そのために必要なのは、グローバルモジュールとapp-module-pathモ​​ジュールです。

ここで「App-module-path」はモジュールです。Node.jsモジュールの検索パスに追加のディレクトリを追加できます。「グローバル」は、このオブジェクトにアタッチしたものはすべてアプリのどこでも使用できます。

次のスニペットを見てください。

global.appBasePath = __dirname;

require('app-module-path').addPath(appBasePath);

__dirnameは、ノードの現在実行中のディレクトリです。ここに独自のパスを指定して、モジュールのパスを検索できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.