process.cwd()실행중인 node.js 프로세스의 루트 디렉토리를 결정하는 것보다 더 좋은 방법이 있습니까? Rails.rootNode.js 와 같은 것과 비슷합니다 . 가능한 한 예측 가능하고 신뢰할 수있는 것을 찾고 있습니다.
process.env.PWD... 아래 내 대답을 참조하십시오.
process.cwd()실행중인 node.js 프로세스의 루트 디렉토리를 결정하는 것보다 더 좋은 방법이 있습니까? Rails.rootNode.js 와 같은 것과 비슷합니다 . 가능한 한 예측 가능하고 신뢰할 수있는 것을 찾고 있습니다.
process.env.PWD... 아래 내 대답을 참조하십시오.
답변:
이것에 접근하는 몇 가지 방법이 있으며, 각각 고유 한 장단점이 있습니다.
에서 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 테스트를 실행 하면이 방법이 실패합니다.
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');
일관되게 작동하지만 전역 변수에 의존해야하므로 구성 요소 등을 쉽게 재사용 할 수 없습니다.
현재 작업 디렉토리를 반환합니다. 이 프로세스가 시작되었다 어떤 디렉토리에 전적으로 의존하는 것에 따라, 전혀하지 신뢰성 에서 :
$ 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 % 작동하지는 않지만 가장 일반적인 시나리오에서는 작동합니다.
대부분의 환경에서 구성없이 작동합니다. 또한 편리한 추가 편리한 방법을 제공합니다 (프로젝트 페이지 참조). 가장 큰 단점은 다음과 같은 경우 작동하지 않는다는 것입니다.
node_modules디렉토리에 설치되지 않은 경우 (예 : 전역으로 설치 한 경우)APP_ROOT_PATH환경 변수 를 설정 하거나 .setPath()모듈 을 호출 하여이 문제를 해결할 수 있지만이 경우 global메소드를 사용하는 것이 좋습니다 .
현재 앱의 루트 경로 를 결정 하는 방법을 찾고 있다면 위의 솔루션 중 하나가 가장 적합 할 것입니다. 반면에 앱 모듈을 안정적으로로드하는 문제를 해결하려는 경우 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] 이 문제를 해결하려는 또 다른 유망한 모듈은 물결 모양 입니다.
require.main.filename
require.main.filename에서 작동하는 것으로 보입니다. 모카에 대해 모른다.
path.parse(process.mainModule.filename).dir
__dirname글로벌이 아닙니다. 현재 모듈에 로컬이므로 각 파일마다 고유 한 로컬 값이 있습니다.
실행중인 프로세스의 루트 디렉토리를 원한다면을 사용하고 싶을 것입니다 process.cwd().
예측 가능성과 신뢰성을 원한다면 특정 환경 변수가 설정되어 있어야합니다. 귀하의 앱은 MY_APP_HOME(또는 무엇이든) 찾아보고 거기에 있으면 응용 프로그램이 해당 디렉토리에 있으면 모든 것이 잘됩니다. 정의되지 않았거나 디렉토리에 응용 프로그램이 포함되어 있지 않으면 변수를 만들라는 오류 메시지와 함께 종료됩니다. 설치 프로세스의 일부로 설정할 수 있습니다.
노드에서 환경 변수를 다음과 같이 읽을 수 있습니다 process.env.MY_ENV_VARIABLE .
bin/server.jsvs를 수행 할 때 다른 결과를 제공 cd bin && server.js합니다. (이 js 파일이 실행 가능한 것으로 표시되어 있다고 가정)
process.cwd()mocha 테스트를 실행할 때도 사용 하는 것이 매력이었습니다. 감사합니다!
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;
이 방법 으로이 파일과 관련된 모든 프로젝트 디렉토리를 갖게됩니다.)
node_modules버전 관리에서 제외되는 경우가 많습니다. 따라서 팀과 함께 작업하거나 리포지토리를 복제해야하는 경우 해당 설정 파일을 동기화 할 수있는 다른 솔루션이 필요합니다.
글로벌 루트를 얻는 가장 쉬운 방법 ( 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')이러한 목적을 위해 아주 잘 작동
PWD정의되지 않아 실패합니다.
process.cwd()
process.cwd()항상 프로젝트 루트와 동일합니까?
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');
나는 이것이 이미 너무 늦었다는 것을 안다. 하지만 두 가지 방법으로 루트 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
INIT_CWD속성이 있습니다 process.env. 이것이 현재 프로젝트에서 작업중 인 것입니다.const {INIT_CWD} = process.env; // process.env.INIT_CWD
const paths = require(`${INIT_CWD}/config/paths`);
행운을 빕니다...
INIT_CWD는 directory에서 실행 된 npm-script것으로 해석됩니다.
메인 파일 상단에 다음을 추가하십시오.
mainDir = __dirname;
그런 다음 필요한 파일로 사용하십시오.
console.log('mainDir ' + mainDir);
mainDir현재 파일에만 필요한 경우 전역 적으로 정의 __dirname됩니다. 대신 사용하십시오.main.js, index.js, gulpfile.js.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
npm install sexy-require --saverequire('sexy-require')기본 애플리케이션 파일 맨 위에 한 번 포함 하십시오.
require('sexy-require');
const routers = require('/routers');
const api = require('$api');
...선택적 단계. 경로 구성은 .paths프로젝트의 루트 디렉토리에 있는 파일에서 정의 할 수 있습니다 .
$db = /server/database
$api-v1 = /server/api/legacy
$api-v2 = /server/api/v2이것은 디렉토리를 포함 할 때까지 디렉토리 트리를 단계적으로 내려 가며, 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리턴 된 경로 가 없는지 확인합니다 . 이는 중첩 된 패키지 설치에 포함되어 있음을 의미합니다.
process.mainModule되어 사용되지 V 14.0.0 때문이다. 답 언급 할 때, 제발 사용require.main, 나머지는 여전히 보유하고 있습니다.
process.mainModule.paths
.filter(p => !p.includes('node_modules'))
.shift()
메인 모듈의 모든 경로를 가져 와서 "node_modules"로 경로를 필터링 한 다음 나머지 경로 목록 중 첫 번째를 가져옵니다. 예기치 않은 동작으로 오류가 발생하지 않습니다 undefined.
ie 호출 할 때도 잘 작동합니다 $ mocha.
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'));
오래된 질문이지만 알고 있지만 질문에 대한 언급은 없습니다. 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 || '';
}
};
전자 앱의 루트 경로를 찾는 것은 까다로울 수 있습니다. 루트 경로는 프로덕션, 개발 및 패키지 된 조건과 같은 다른 조건에서 기본 프로세스 및 렌더러에 대해 다르기 때문입니다.
전자 응용 프로그램의 루트 경로를 캡처하기 위해 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' });
전문
이것은 매우 오래된 질문이지만 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를 설치하는 것은 드문 일이 아니며 안전 하지도 않습니다. ). 위에서 설명한대로 폴백으로 중재 할 수 있습니다.
노트
export 그것을 모듈로 만드는 기능참고 문헌