[node.js] 실행중인 node.js 애플리케이션에서 프로젝트 루트 결정

process.cwd()실행중인 node.js 프로세스의 루트 디렉토리를 결정하는 것보다 더 좋은 방법이 있습니까? Rails.rootNode.js 와 같은 것과 비슷합니다 . 가능한 한 예측 가능하고 신뢰할 수있는 것을 찾고 있습니다.



답변

이것에 접근하는 몇 가지 방법이 있으며, 각각 고유 한 장단점이 있습니다.

require.main.filename

에서 http://nodejs.org/api/modules.html :

파일이 Node에서 직접 실행될 때이로 require.main설정됩니다 module. 즉, 테스트를 통해 파일이 직접 실행되었는지 확인할 수 있습니다.require.main === module

때문에 module제공 filename속성 (정상적으로 당량 __filename), 현재 어플리케이션의 엔트리 포인트를 선택하여 얻을 수있다 require.main.filename.

따라서 앱의 기본 디렉토리를 원하면 다음을 수행 할 수 있습니다.

var path = require('path');
var appDir = path.dirname(require.main.filename);

찬반 양론

대부분의 경우 잘 작동하지만 pm2 와 같은 실행기로 앱을 실행하거나 mocha 테스트를 실행 하면이 방법이 실패합니다.

global.X

Node에는 전역 네임 스페이스 global객체가 있습니다.이 객체에 첨부하는 모든 것은 앱의 모든 곳에서 사용할 수 있습니다. 따라서 index.js(또는 app.js기본 앱 파일 이름에 관계없이) 전역 변수를 정의하면됩니다.

// index.js
var path = require('path');
global.appRoot = path.resolve(__dirname);

// lib/moduleA/component1.js
require(appRoot + '/lib/moduleB/component2.js');

찬반 양론

일관되게 작동하지만 전역 변수에 의존해야하므로 구성 요소 등을 쉽게 재사용 할 수 없습니다.

process.cwd ()

현재 작업 디렉토리를 반환합니다. 이 프로세스가 시작되었다 어떤 디렉토리에 전적으로 의존하는 것에 따라, 전혀하지 신뢰성 에서 :

$ cd /home/demo/
$ mkdir subdir
$ echo "console.log(process.cwd());" > subdir/demo.js
$ node subdir/demo.js
/home/demo
$ cd subdir
$ node demo.js
/home/demo/subdir

앱 루트 경로

이 문제를 해결하기 위해 app-root-path 라는 노드 모듈을 만들었습니다 . 사용법은 간단합니다.

var appRoot = require('app-root-path');
var myModule = require(appRoot + '/lib/my-module.js');

응용 프로그램 루트 경로 모듈은 앱에서 실행중인 경우 (예를 들어, 계정으로 전 세계적으로 설치된 모듈을 복용, 응용 프로그램의 루트 경로를 결정하기 위해 여러 가지 기술을 사용 /var/www/하지만 모듈이 설치되어~/.nvm/v0.x.x/lib/node/ ). 100 % 작동하지는 않지만 가장 일반적인 시나리오에서는 작동합니다.

찬반 양론

대부분의 환경에서 구성없이 작동합니다. 또한 편리한 추가 편리한 방법을 제공합니다 (프로젝트 페이지 참조). 가장 큰 단점은 다음과 같은 경우 작동하지 않는다는 것입니다.

  • pm2와 같은 실행기를 사용하고 있습니다.
  • AND , 모듈이 앱의 node_modules디렉토리에 설치되지 않은 경우 (예 : 전역으로 설치 한 경우)

APP_ROOT_PATH환경 변수 를 설정 하거나 .setPath()모듈 을 호출 하여이 문제를 해결할 수 있지만이 경우 global메소드를 사용하는 것이 좋습니다 .

NODE_PATH 환경 변수

현재 앱의 루트 경로 를 결정 하는 방법을 찾고 있다면 위의 솔루션 중 하나가 가장 적합 할 것입니다. 반면에 앱 모듈을 안정적으로로드하는 문제를 해결하려는 경우 NODE_PATH환경 변수를 조사하는 것이 좋습니다 .

노드 모듈 시스템 은 다양한 위치에서 모듈을 찾습니다. 이 위치 중 하나는 어디든지 process.env.NODE_PATH포인트 입니다. 이 환경 변수를 설정하면 require다른 변경없이 표준 모듈 로더가있는 모듈 을 사용할 수 있습니다 .

예를 들어, 설정하면 NODE_PATH할 수 /var/www/lib는 다음과 같은 상황이 잘 작동합니다 :

require('module2/component.js');
// ^ looks for /var/www/lib/module2/component.js

이를 수행하는 가장 좋은 방법은 다음을 사용하는 것입니다 npm.

"scripts": {
    "start": "NODE_PATH=. node app.js"
}

이제 앱을 시작할 npm start수 있으며 황금색입니다. 이것을 강제 노드 경로 모듈 과 결합하여 NODE_PATH설정 하지 않고 실수로 앱을로드하지 못하게 합니다. 환경 변수 시행에 대한 더 많은 제어는 checkenv를 참조하십시오 .

하나의 문제 : 노드 앱 외부 에 설정 NODE_PATH 해야합니다 . 모듈 로더는 앱이 실행되기 전에 검색 할 디렉토리 목록을 캐시하기 때문에 이와 같은 작업을 수행 할 수 없습니다 .process.env.NODE_PATH = path.resolve(__dirname)

[add 4/6/16] 이 문제를 해결하려는 또 다른 유망한 모듈은 물결 모양 입니다.


답변

__dirname글로벌이 아닙니다. 현재 모듈에 로컬이므로 각 파일마다 고유 한 로컬 값이 있습니다.

실행중인 프로세스의 루트 디렉토리를 원한다면을 사용하고 싶을 것입니다 process.cwd().

예측 가능성과 신뢰성을 원한다면 특정 환경 변수가 설정되어 있어야합니다. 귀하의 앱은 MY_APP_HOME(또는 무엇이든) 찾아보고 거기에 있으면 응용 프로그램이 해당 디렉토리에 있으면 모든 것이 잘됩니다. 정의되지 않았거나 디렉토리에 응용 프로그램이 포함되어 있지 않으면 변수를 만들라는 오류 메시지와 함께 종료됩니다. 설치 프로세스의 일부로 설정할 수 있습니다.

노드에서 환경 변수를 다음과 같이 읽을 수 있습니다 process.env.MY_ENV_VARIABLE .


답변

1- 프로젝트 루트에 파일을 만듭니다. settings.js

2-이 파일 안에이 코드를 추가하십시오

module.exports = {
    POST_MAX_SIZE : 40 , //MB
    UPLOAD_MAX_FILE_SIZE: 40, //MB
    PROJECT_DIR : __dirname
};

3- 내부 node_modules는 “설정”이라는 새 모듈 이름을 만들고 모듈 index.js 안에 다음 코드를 작성합니다.

module.exports = require("../../settings");

4-프로젝트 디렉토리를 원할 때마다

var settings = require("settings");
settings.PROJECT_DIR; 

이 방법 으로이 파일과 관련된 모든 프로젝트 디렉토리를 갖게됩니다.)


답변

글로벌 루트를 얻는 가장 쉬운 방법 ( NPM을 사용하여 node.js 앱 ‘npm start’등을 가정 할 때 )

var appRoot = process.env.PWD;

위의 내용을 교차 확인하려면

process.env.PWDnode.js 응용 프로그램의 설정 으로 교차 확인을 원한다고 가정 해보십시오. 의 런타임 유효성 검사를 위해 런타임 테스트를 원한다면 process.env.PWD이 코드를 사용하여 교차 검사 할 수 있습니다 (필자는 잘 작동하는 것 같습니다). package.json 파일의 npm_package_name을 사용하여 appRoot의 마지막 폴더 이름을 교차 검사 할 수 있습니다. 예를 들면 다음과 같습니다.

    var path = require('path');

    var globalRoot = __dirname; //(you may have to do some substring processing if the first script you run is not in the project root, since __dirname refers to the directory that the file is in for which __dirname is called in.)

    //compare the last directory in the globalRoot path to the name of the project in your package.json file
    var folders = globalRoot.split(path.sep);
    var packageName = folders[folders.length-1];
    var pwd = process.env.PWD;
    var npmPackageName = process.env.npm_package_name;
    if(packageName !== npmPackageName){
        throw new Error('Failed check for runtime string equality between globalRoot-bottommost directory and npm_package_name.');
    }
    if(globalRoot !== pwd){
        throw new Error('Failed check for runtime string equality between globalRoot and process.env.PWD.');
    }

: 당신은이 NPM 모듈을 사용할 수 있습니다 require('app-root-path')이러한 목적을 위해 아주 잘 작동


답변

Mocha와 같은 일부 테스트 프레임 워크에서와 같이 하위 폴더에서 응용 프로그램을 호출 하더라도이 기능이 지속적으로 작동한다는 것을 알았습니다.

process.mainModule.paths[0].split('node_modules')[0].slice(0, -1);

작동하는 이유 :

런타임시 노드는로드 된 모든 파일의 전체 경로에 대한 레지스트리를 작성합니다. 모듈이 먼저로드되므로이 레지스트리의 맨 위에로드됩니다. 레지스트리의 첫 번째 요소를 선택하고 ‘node_modules’디렉토리 앞의 경로를 리턴하여 애플리케이션의 루트를 판별 할 수 있습니다.

그것은 단지 한 줄의 코드이지만, 편의상 (나를 위해) NPM 모듈에 블랙 박스로 넣었습니다.

https://www.npmjs.com/package/node-root.pddivine

즐겨!


답변

이러한 모든 “루트 디렉토리”는 대부분 실제 파일 경로에 대한 가상 경로를 해결해야하므로 살펴보아야 path.resolve할까요?

var path= require('path');
var filePath = path.resolve('our/virtual/path.ext');


답변

이 줄을 루트로 모듈에 추가하는 것처럼 간단합니다. 일반적으로 app.js입니다.

global.__basedir = __dirname;

그러면 _basedir은 모든 모듈에 액세스 할 수 있습니다.