261

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

たとえば、https://github.com/visionmedia/express/blob/2820f2227de0229c5d7f28009aa432f9f3a7b5f9/examples/downloads/app.jsの6行目を見ると次のようになります。

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

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

express = require('../')

私の解決策は、ルートベースの特別なケースを用意することです。文字列が$で始まる場合、それはプロジェクトのルートフォルダに相対的です。

どんな助けでもありがたいです、ありがとう

アップデート2

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

アップデート3

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

4

37 に答える 37

171

そして何について:

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

メインのjsファイルから必要とされるかのようにファイルを必要とするため、メインのjsファイルがプロジェクトのルートにある限り、かなりうまく機能します...そしてそれは私が感謝するものです.

于 2014-10-02T15:09:56.807 に答える
131

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

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

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

node_modules

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

答えはとても簡単です!.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 で構成された変換があった場合、モジュールの境界を越えて変換が適用されないため、独自の変換フィールドを持つ別の package.json を自分のnode_modules/fooまたはコンポーネント ディレクトリに作成する必要があります。node_modules/app/fooこれにより、モジュールはアプリケーションの構成変更に対してより堅牢になり、アプリケーションの外部でパッケージを個別に再利用することが容易になります。

シンボリックリンク

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

ln -s ../lib node_modules/app

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

カスタム パス

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

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

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

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

于 2014-07-08T11:44:37.890 に答える
40

大きな絵

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

このように考えてみてください: あなたは例を読んで Node.js に足​​を踏み入れ、それが「本当に悪い IMO」であると判断しました。あなたは、Node.js コミュニティーのリーダーであり、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')

例/ダウンロード/express.js

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

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

于 2012-06-02T10:50:35.950 に答える
21

npmの代わりにyarnを使用している場合は、ワークスペースを使用できます。

servicesもっと簡単に要求したいフォルダがあるとしましょう:

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

Yarn ワークスペースを作成するには、以下の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')
于 2018-11-06T19:52:16.510 に答える
20

node-rfrを見てください。

次のように簡単です。

var rfr = require('rfr');
var myModule = rfr('projectSubDir/myModule');
于 2014-04-16T11:24:53.607 に答える
14

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

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

requireこれで絶対パスになることは注目に値するかもしれませんが、私はまだこれに関する問題に遭遇していません.

于 2015-06-10T04:11:31.747 に答える
13

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示した写真を表示したほうがよいでしょう。

于 2012-06-02T19:27:38.527 に答える
5

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

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

その後、どこからでもプロパティにアクセスできます。

// in app.js
express = require(process.env.root);
于 2015-05-21T01:23:50.313 に答える
5

手動シンボリック リンク (および Windows ジャンクション)

プロジェクトのルートへのシンボリック リンクを含む をexamplesディレクトリに含めることができなかったため、例で を使用できませんでした。node_modulesproject -> ../../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.js、オブジェクトのプロパティに値を割り当て、それが必要であったことを示すメッセージでexports呼び出します。console.logの内容test.jsrequire('project').

自動シンボリックリンク

手動でシンボリック リンクを作成する場合の問題は、毎回シンボリック リンクnpm ciを失うことです。symlink プロセスを依存関係にすれば、viola は問題ありません。

モジュールは、実行されるたびに名前がbasetag付けられたシンボリック リンク (または Windows ジャンクション) を作成するポストインストール スクリプトです。$npm installnpm ci

npm install --save basetag
node_modules/$ -> ..

これにより、コードを特別に変更したり、システムを必要としたりする必要はありません。$要求できるルートになります。

var foo = require('$/lib/foo.js');

$andの使用が気に入らない場合#や、または他の何か ( @npm の特殊文字である を除く) を使用する場合は、フォークして変更することができます。

注: Windows シンボリック リンク (ファイルへ) には管理者権限が必要ですが、Windows ジャンクション (ディレクトリへ)には Windows 管理者権限は必要ありません。これは、安全で信頼性の高いクロスプラットフォーム ソリューションです。

于 2012-06-02T07:55:32.240 に答える
4

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

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

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

于 2013-01-16T00:12:52.443 に答える
2

私がやりたいのは、ノードが node_module ディレクトリからどのようにロードされるかを活用することです。

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

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';
于 2016-01-27T07:27:08.743 に答える
2

私は何度も同じ問題を抱えていました。basetagこれは、 npm パッケージを使用することで解決できます。それ自体を必要とする必要はありませんnode_modules。ベース パス内にシンボリック リンクを作成するときにインストールするだけです。

const localFile = require('$/local/file')
// instead of
const localFile = require('../../local/file')

プレフィックスを使用する$/...と、アプリのルート ディレクトリに相対的なファイルが常に参照されます。

出典basetag:この問題を解決するために私が作成した方法

于 2020-04-24T09:48:21.650 に答える
1

「rekiure」というノードモジュールを作成しました

相対パスを使用せずに要求することができます

https://npmjs.org/package/rekuire

とても使いやすいです

于 2013-03-28T10:03:43.193 に答える
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.module1;

必要に応じて、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ます。これにより、環境に応じてさまざまなモジュールを使用できますが、このスレッドの範囲外になります。

于 2014-01-07T13:21:09.773 に答える
1

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

npm install --save rootpath

...次に、エントリ ポイント js ファイルの一番上に、次を追加します。

require('rootpath')();

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

于 2015-09-11T05:43:19.213 に答える
1

簡単な行で、独自のフォルダーを module として呼び出すことができます:

そのために必要なもの: global および app-module-path モジュール

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

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

global.appBasePath = __dirname;

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

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

于 2016-09-29T14:53:46.323 に答える
-1

あなたが説明した方法でこれを解決する必要はないと思います。大量のファイルで同じ文字列を変更したい場合は、単に sed を実行してください。あなたの例では、

find . -name "*.js" -exec sed -i 's/\.\.\/\.\.\//\.\.\//g' {} +

../../ は ../ に変更されます。

または、ライブラリへのパスを含む変数を格納する構成ファイルを要求することもできます。exampleディレクトリに以下をconfig.jsとして格納すると

var config = {};
config.path = '../../';

そしてあなたのサンプルファイルで

myConfiguration = require('./config');
express = require(config.path);

1 つのファイルからすべての例の構成を制御できます。

それは本当に個人的な好みです。

于 2012-06-02T06:55:40.783 に答える