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


315

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


1
받아 들여지고 틀린 대답을 받아들이지 않을 수 있습니까?
Dave Newton

9
시도 process.env.PWD... 아래 내 대답을 참조하십시오.
Alexander Mills

답변:


624

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

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] 이 문제를 해결하려는 또 다른 유망한 모듈은 물결 모양 입니다.


1
이 경우 @Kevin, mocha는 응용 프로그램의 진입 점입니다. 이것은 "프로젝트 루트"를 찾는 것이 왜 어려운지에 대한 예일뿐입니다. 상황과 "프로젝트 루트"의 의미에 따라 크게 다릅니다.
inxilpro

1
@Kevin 나는 완전히 이해한다. 내 요점은 "프로젝트 루트"라는 개념이 컴퓨터 보다 인간 이 이해 하기 훨씬 쉽다 는 입니다. 확실한 방법을 원하면 구성해야합니다. 사용하여 작동 가장 하지만, 시간을 모든 시간. require.main.filename
inxilpro

2
접선 적으로 관련됨 : 노드 프로젝트를 구성하는 매우 영리한 방법으로이 문제에 대해 너무 걱정할 필요가 없습니다. 이므로이 allanhortle.com/2015/02/04/…
inxilpro

1
pm2에 변경이 있었는지 Node.js에 대한 변경이 있었는지 모르지만 pm2 require.main.filename에서 작동하는 것으로 보입니다. 모카에 대해 모른다.
저스틴 Warkentin

8
path.parse(process.mainModule.filename).dir
코리 로빈슨

53

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

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

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

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


2
주의해서 사용하면 꽤 잘 작동 할 수 있습니다. 그러나 bin/server.jsvs를 수행 할 때 다른 결과를 제공 cd bin && server.js합니다. (이 js 파일이 실행 가능한 것으로 표시되어 있다고 가정)
Myrne Stol

1
process.cwd()mocha 테스트를 실행할 때도 사용 하는 것이 매력이었습니다. 감사합니다!
Diogo Eichert

49

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; 

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


33
-1 : 설정 파일을로드하려면 경로가 필요하며 해당 파일의 참조 경로를 가져 오시겠습니까? 아무것도 해결하지 않고 ...
goliatone

2
검토하고 편집하는 데 시간이 걸리는 것에 찬성했습니다. 그것은 여전히 ​​부서지기 쉬운 느낌이지만, 이것을 달성하는 더 좋은 방법이 없기 때문일 수 있습니다.
goliatone

8
사용자가이 접근 방식을 염두에두고 싶은 것은 node_modules버전 관리에서 제외되는 경우가 많습니다. 따라서 팀과 함께 작업하거나 리포지토리를 복제해야하는 경우 해당 설정 파일을 동기화 할 수있는 다른 솔루션이 필요합니다.
Travesty3

@ Travesty3 설정 모듈은 실제로 프로젝트 루트에서 파일의 내용을 내보내는 빈 모듈입니다 .P
Fareed Alnamrouti

@goliatone 그의 솔루션을 사용하면 경로를 몰라도 어디에서나 파일을 얻을 수 있습니다. "설정"만 있으면됩니다. 이것이 없으면 프로젝트 디렉토리에 도달 할 때까지 얼마나 많은 폴더를 제거해야하는지 명시 적으로 알아야합니다. 이것은 node가 node_modules를 자동으로 검색하고 그 위치를 항상 알고 있기 때문에 작동합니다.

26

글로벌 루트를 얻는 가장 쉬운 방법 ( 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')이러한 목적을 위해 아주 잘 작동


5
이것은 (대부분의) 유닉스 시스템에서 잘 작동합니다. npm 모듈 / 앱이 Windows에서 작동하자마자 PWD정의되지 않아 실패합니다.
Jeremy Wiebe

1
process.cwd()
Muhammad Umer

@MuhammadUmer는 왜 process.cwd()항상 프로젝트 루트와 동일합니까?
Alexander Mills

루트 파일을 호출하는 경우 그것은 것
무하마드 Umer

14

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

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

작동하는 이유 :

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

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

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

즐겨!


1
process.mainModule v14.0.0부터 사용 require.main.paths[0].split('node_modules')[0].slice(0, -1);되지 않음 - 대신 사용하십시오.
RobC

10

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

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

9

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

global.__basedir = __dirname;

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


8

__filename를 찾을 때까지 위쪽에서 순회를 시도 package.json하여 현재 파일이 속한 기본 디렉토리인지 결정할 수 있습니다.


7

실제로, 아마도 가장 강력한 해결책 일 수도 있습니다. 프로젝트의 루트 디렉토리에 다음 파일을 간단히 배치하십시오 : root-path.js에는 다음 코드가 있습니다.

import * as path from 'path'
const projectRootPath = path.resolve(__dirname)
export const rootPath = projectRootPath

4

Express를 사용할 때 유용하다고 생각한 기술은 다른 경로가 설정되기 전에 app.js에 다음을 추가하는 것입니다.

// set rootPath
app.use(function(req, res, next) {
  req.rootPath = __dirname;
  next();
});

app.use('/myroute', myRoute);

글로벌을 사용할 필요가 없으며 요청 오브젝트의 특성으로 루트 디렉토리의 경로가 있습니다.

app.js가 기본적으로 프로젝트의 루트에있는 경우 작동합니다.


4

메인 앱 파일의 시작 부분에 이것을 추가하십시오 (예 : app.js) :

global.__basedir = __dirname;

이것은 항상 앱의 기본 디렉토리와 동등한 전역 변수를 설정합니다. 다른 변수와 마찬가지로 사용하십시오.

const yourModule = require(__basedir + '/path/to/module.js');

단순한...


3

나는 이것이 이미 너무 늦었다는 것을 안다. 하지만 두 가지 방법으로 루트 URL을 가져올 수 있습니다

첫 번째 방법

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

두 번째 방법

var path = require('path');
path.dirname(process.mainModule.filename);

참조 링크 :-https: //gist.github.com/geekiam/e2e3e0325abd9023d3a3


3

INIT_CWD속성이 있습니다 process.env. 이것이 현재 프로젝트에서 작업중 인 것입니다.

const {INIT_CWD} = process.env; // process.env.INIT_CWD 
const paths = require(`${INIT_CWD}/config/paths`);

행운을 빕니다...


1
설치 후 단계에서 호출되는 프로젝트를 조작하는 패키지의 매력처럼 작동했습니다. 그러나 프로젝트가 내 패키지를 사용하는 종속성을 사용하는 다른 종속성 계층에서 아직 테스트하지 않았습니다.
JamesDev

1
@JamesDev INIT_CWDdirectory에서 실행 된 npm-script것으로 해석됩니다.
Akash

2

실행중인 node.js 응용 프로그램에서 프로젝트 루트를 결정하려면 간단하게 할 수 있습니다.

process.mainModule.path

1

메인 파일 상단에 다음을 추가하십시오.

mainDir = __dirname;

그런 다음 필요한 파일로 사용하십시오.

console.log('mainDir ' + mainDir);
  • mainDir현재 파일에만 필요한 경우 전역 적으로 정의 __dirname됩니다. 대신 사용하십시오.
  • 기본 파일은 프로젝트의 루트 폴더에 보통과 같이 이름이 main.js, index.js, gulpfile.js.

1

나는 이것을 사용합니다.

내 모듈 이름 mymodule

var BASE_DIR = __dirname.replace(/^(.*\/mymodule)(.*)$/, '$1')


1

섹시하게 만드세요.

const users = require('../../../database/users'); // 👎 what you have
// OR
const users = require('$db/users'); // 👍 no matter how deep you are
const products = require('/database/products'); // 👍 alias or pathing from root directory


추악한 길 문제를 해결하기위한 세 가지 간단한 단계.

  1. 패키지를 설치하십시오 : npm install sexy-require --save
  2. require('sexy-require')기본 애플리케이션 파일 맨 위에 한 번 포함 하십시오.

    require('sexy-require');
    const routers = require('/routers');
    const api = require('$api');
    ...
  3. 선택적 단계. 경로 구성은 .paths프로젝트의 루트 디렉토리에 있는 파일에서 정의 할 수 있습니다 .

    $db = /server/database
    $api-v1 = /server/api/legacy
    $api-v2 = /server/api/v2

괜찮은 것 같고 너무 나빴습니다.
JHH

@JHH 잘 ... 나는 더 나은 이름을 찾아야했다
sultan

1

이것은 디렉토리를 포함 할 때까지 디렉토리 트리를 단계적으로 내려 가며, node_modules일반적으로 프로젝트 루트를 나타냅니다.

const fs = require('fs')
const path = require('path')

function getProjectRoot(currentDir = __dirname.split(path.sep)) {
  if (!currentDir.length) {
    throw Error('Could not find project root.')
  }
  const nodeModulesPath = currentDir.concat(['node_modules']).join(path.sep)
  if (fs.existsSync(nodeModulesPath) && !currentDir.includes('node_modules')) {
    return currentDir.join(path.sep)
  }
  return this.getProjectRoot(currentDir.slice(0, -1))
}

또한 node_modules리턴 된 경로 가 없는지 확인합니다 . 이는 중첩 된 패키지 설치에 포함되어 있음을 의미합니다.


1

process.mainModule되어 사용되지 V 14.0.0 때문이다. 답 언급 할 때, 제발 사용 require.main , 나머지는 여전히 보유하고 있습니다.

process.mainModule.paths
  .filter(p => !p.includes('node_modules'))
  .shift()

메인 모듈의 모든 경로를 가져 와서 "node_modules"로 경로를 필터링 한 다음 나머지 경로 목록 중 첫 번째를 가져옵니다. 예기치 않은 동작으로 오류가 발생하지 않습니다 undefined.

ie 호출 할 때도 잘 작동합니다 $ mocha.


0

app.js에서 함수 만들기

/*Function to get the app root folder*/

var appRootFolder = function(dir,level){
    var arr = dir.split('\\');
    arr.splice(arr.length - level,level);
    var rootFolder = arr.join('\\');
    return rootFolder;
}

// view engine setup
app.set('views', path.join(appRootFolder(__dirname,1),'views'));

0

express 앱 변수에 루트 디렉토리 경로를 추가하고 앱에서이 경로를 가져올 수 있습니다. 이를 app.set('rootDirectory', __dirname);위해 index.js 또는 app.js 파일에 추가 하십시오. req.app.get('rootDirectory')코드에서 루트 디렉토리 경로를 얻는 데 사용 하십시오.


0

오래된 질문이지만 알고 있지만 질문에 대한 언급은 없습니다. progress.argv . argv 배열에는 노드에서 실행할 매개 변수로 사용 된 전체 경로 이름 및 파일 이름 (.js 확장자가 있거나없는)이 포함됩니다. 여기에는 플래그도 포함될 수 있으므로이를 필터링해야합니다.

이것은 (내 자신의 프레임 워크를 사용하기 때문에) 직접 사용할 수있는 예는 아니지만 어떻게 해야하는지에 대한 아이디어를 제공한다고 생각합니다. 또한 캐시 함수를 사용하여이 함수를 호출하면 시스템에 너무 많은 스트레스를 피할 수 있습니다. 특히 확장자가 지정되어 있지 않고 파일이 있는지 확인해야하는 경우에는 다음과 같습니다.

node myfile

또는

node myfile.js

그것이 내가 캐시하는 이유입니다. 아래 코드도 참조하십시오.


function getRootFilePath()
{
        if( !isDefined( oData.SU_ROOT_FILE_PATH ) )
        {
            var sExt = false;

            each( process.argv, function( i, v )
            {
                 // Skip invalid and provided command line options
                if( !!v && isValidString( v ) && v[0] !== '-' )
                {
                    sExt = getFileExt( v );

                    if( ( sExt === 'js' ) || ( sExt === '' && fileExists( v+'.js' )) )
                    {

                        var a = uniformPath( v ).split("/"); 

                         // Chop off last string, filename
                        a[a.length-1]='';

                         // Cache it so we don't have to do it again.
                        oData.SU_ROOT_FILE_PATH=a.join("/"); 

                         // Found, skip loop
                        return true;
                    }
                }
            }, true ); // <-- true is: each in reverse order
        }

        return oData.SU_ROOT_FILE_PATH || '';
    }
}; 

0

전자 앱의 루트 경로를 찾는 것은 까다로울 수 있습니다. 루트 경로는 프로덕션, 개발 및 패키지 된 조건과 같은 다른 조건에서 기본 프로세스 및 렌더러에 대해 다르기 때문입니다.

전자 응용 프로그램의 루트 경로를 캡처하기 위해 npm 패키지 electron-root-path 를 작성했습니다 .

$ npm install electron-root-path

or 

$ yarn add electron-root-path


// Import ES6 way
import { rootPath } from 'electron-root-path';

// Import ES2015 way
const rootPath = require('electron-root-path').rootPath;

// e.g:
// read a file in the root
const location = path.join(rootPath, 'package.json');
const pkgInfo = fs.readFileSync(location, { encoding: 'utf8' });



0

전문

이것은 매우 오래된 질문이지만 2012 년과 같이 2020 년에도 여전히 신경을 치는 것 같습니다. 나는 다른 모든 답변을 확인했지만 기술을 찾을 수 없었습니다 (이에는 한계가 있지만 나머지는 그렇지 않습니다. 모든 상황에서 적용 가능).

GIT + 자식 프로세스

GIT를 버전 제어 시스템으로 사용하는 경우 프로젝트 루트를 결정하는 문제를 줄일 수 있습니다 (프로젝트의 올바른 루트를 고려할 것입니다. 결국 VCS가 가능한 최대 가시성 범위를 갖기를 원할 것입니다) :

검색 저장소 루트 경로

이를 위해 CLI 명령을 실행해야하므로 하위 프로세스를 생성해야합니다. 또한 프로젝트 루트가 런타임 중 변경되지 않을 가능성이 높으므로 child_process시작시 동기 버전의 모듈 API를 사용할 수 있습니다 .

나는 spawnSync()직업에 가장 적합한 것으로 나타났습니다 . 실제 명령을 실행하는 경우 git worktree( --porcelain파싱 ​​용이성을위한 옵션으로) 절대 루트 경로를 검색하는 데 필요한 전부입니다.

이 샘플에서는 하나 이상의 작업 트리가있을 수 있기 때문에 경로 배열을 반환하기로 선택했습니다 (공통 경로가있을 수는 있지만). CLI 명령을 사용할 때 shell옵션을 다음과 같이 설정해야합니다.true (신뢰할 수없는 입력이 없으므로 보안은 문제가되지 않습니다).

접근법 비교 및 ​​대체

VCS에 액세스 할 수없는 상황을 이해하기 위해 문서 및 기타 답변을 분석 한 후 몇 가지 폴백을 포함 시켰습니다. 요약하자면 제안 된 솔루션은 다음과 같이 요약됩니다 (타사 모듈 및 패키지 별 제외).

| 솔루션 | 장점 | 주요 문제 |
| ------------------------ | ----------------------- | -------------------------------- |
| `__ 파일 이름`| 모듈 파일을 가리킴 | 모듈 기준 |
| `__dirname` | 모듈 디렉토리를 가리킴 | `__filename`과 동일 |
| `node_modules` 트리 워크 | 거의 보장 된 루트 | 중첩 된 경우 복잡한 나무 걷기 |
| `path.resolve ( ".")`| CWD가 루트 인 경우 루트 | `process.cwd ()`와 동일 |
| `process.argv [1]`| `__filename`과 동일 | `__filename`과 동일 |
| `process.env.INIT_CWD` | npm run` dir을 가리 킵니다. `npm`이 필요하며 && CLI 시작 |
| `process.env.PWD` | 현재 디렉토리를 가리 킵니다 | 시작 디렉토리에 상대적인 (있는) |
| `process.cwd ()`| `env.PWD`와 동일 | 런타임시`process.chdir (path)`|
| `require.main.filename` | `=== module` 인 경우 루트 | `요구 사항 '모듈에서 실패 |

위의 비교 표에서 가장 보편적 인 방법은 두 가지입니다.

  • require.main.filenamerequire.main === module충족 되면 루트를 얻는 쉬운 방법으로
  • node_modules제안 된 트리 워크는 최근에 다른 가정을 사용합니다.

모듈의 디렉토리에 node_modulesdir이 있으면 루트 일 가능성이 높습니다

메인 앱의 경우 앱 루트와 모듈-프로젝트 루트를 가져옵니다.

폴백 1. 나무 산책

내 구현은 주어진 모듈에 대해 대상 디렉토리가 발견되면 루트가 프로젝트 루트 인 경우 중지하여보다 느슨한 접근 방식을 사용합니다. 검색 깊이를 구성 할 수 있도록 통화를 연결하거나 확장 할 수 있습니다.

/**
 * @summary gets root by walking up node_modules
 * @param {import("fs")} fs
 * @param {import("path")} pt
 */
const getRootFromNodeModules = (fs, pt) =>

    /**
     * @param {string} [startPath]
     * @returns {string[]}
     */
    (startPath = __dirname) => {

        //avoid loop if reached root path
        if (startPath === pt.parse(startPath).root) {
            return [startPath];
        }

        const isRoot = fs.existsSync(pt.join(startPath, "node_modules"));

        if (isRoot) {
            return [startPath];
        }

        return getRootFromNodeModules(fs, pt)(pt.dirname(startPath));
    };

폴백 2. 메인 모듈

두 번째 구현은 간단합니다

/**
 * @summary gets app entry point if run directly
 * @param {import("path")} pt
 */
const getAppEntryPoint = (pt) =>

    /**
     * @returns {string[]}
     */
    () => {

        const { main } = require;

        const { filename } = main;

        return main === module ?
            [pt.parse(filename).dir] :
            [];
    };

이행

트리 워커를 더 다양한 용도로 사용하는 것이 좋습니다.

const { spawnSync } = require("child_process");
const pt = require('path');
const fs = require("fs");

/**
 * @summary returns worktree root path(s)
 * @param {function : string[] } [fallback]
 * @returns {string[]}
 */
const getProjectRoot = (fallback) => {

    const { error, stdout } = spawnSync(
        `git worktree list --porcelain`,
        {
            encoding: "utf8",
            shell: true
        }
    );

    if (!stdout) {
        console.warn(`Could not use GIT to find root:\n\n${error}`);
        return fallback ? fallback() : [];
    }

    return stdout
        .split("\n")
        .map(line => {
            const [key, value] = line.split(/\s+/) || [];
            return key === "worktree" ? value : "";
        })
        .filter(Boolean);
};

단점

가장 명백한 것은 바람직하지 않거나 불가능한 GIT를 설치하고 초기화하는 것입니다 (참고 : 프로덕션 서버에 GIT를 설치하는 것은 드문 일이 아니며 안전 하지도 않습니다. ). 위에서 설명한대로 폴백으로 중재 할 수 있습니다.

노트

  1. 접근 방식의 추가 확장을위한 몇 가지 아이디어 1 :
    • 기능 매개 변수로 구성 소개
    • export 그것을 모듈로 만드는 기능
    • GIT가 설치 및 / 또는 초기화되었는지 확인

참고 문헌

  1. git worktree 참고
  2. spawnSync 참고
  3. require.main 참고
  4. path.dirname() 참고


-1

시험 path._makeLong('some_filename_on_root.js');

예:

cons path = require('path');
console.log(path._makeLong('some_filename_on_root.js');

노드 응용 프로그램의 루트 (package.json과 동일한 위치)에서 전체 경로를 반환합니다.


-1

그냥 사용하십시오 :

 path.resolve("./") ... output is your project root directory

이것은 잘 작동합니다! path.resolve는 ( ".")뿐만 아니라 작동합니다
노엘 솅크에게

루트 디렉토리가 아닌 현재 디렉토리 만 제공합니다.
orad

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.