node.js를 절대적으로 요구하는 방법? (상대가 아닌)


234

현재 모듈이 아닌 프로젝트의 루트에 따라 항상 파일을 요구하고 싶습니다.

예를 들어 https://github.com/visionmedia/express/blob/2820f2227de0229c5d7f28009aa432f9f3a7b5f9/examples/downloads/app.js 6 번 줄을 보면

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

정말 나쁜 IMO입니다. 모든 예제를 한 수준 만 루트에 더 가깝게하고 싶다고 상상해보십시오. 각 예제 내에서 30 개 이상의 예제를 여러 번 업데이트해야하기 때문에 불가능합니다. 이에:

express = require('../')

내 솔루션은 루트 기반의 특별한 경우를 갖는 것입니다. 문자열이 $로 시작하면 프로젝트의 루트 폴더와 관련이 있습니다.

도움을 주셔서 감사합니다

업데이트 2

이제 require.js를 사용하여 한 가지 방식으로 작성하고 클라이언트와 서버에서 모두 작동합니다. Require.js를 사용하면 사용자 지정 경로를 만들 수도 있습니다.

업데이트 3

이제 webpack + gulp로 이동했으며 서버 측에서 모듈을 처리하기 위해 강화 요구 사항을 사용합니다. 근거를 여기에서보십시오 : http://hackhat.com/p/110/module-loader-webpack-vs-requirejs-vs-browserify/


명시 적 루트 경로 상수 / 변수를 사용하기로 결정한 경우이 답변이 효과적입니다 . 솔루션은 작은 github 모듈을 사용하여 루트 경로를 결정합니다.
steampowered

답변:


162

그리고 어떻습니까 :

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

기본 js 파일에서 필요한 것처럼 파일이 필요하므로 기본 js 파일이 프로젝트의 루트에있는 한 꽤 잘 작동합니다.


나쁜 생각은 아닙니다 (: 그런 다음 require.main 모듈에서 앱을 다시 매핑하는 다른 방법을 정의 할 수 있습니다. 그러면 require.main.req ( 'client / someMod') 할 수 있다고 생각합니다. 그러나 좋은 생각입니다. 또한 내 코드가 브라우저와 node.js에서 모두 실행되어야하기 때문에 변경 사항이 즉각적이지 않고 변경 사항을 놓치기 때문에 browserify를 싫어하기 때문에 가치가 있다고 생각하지 않습니다.
Totty.js

4
너무 장황한 경우 .bind ()를 사용하십시오. var rootReq = require.bind (require.main); rootReq ( './path/to/module');
cronvel

예, 이것은 클라이언트 측에서 여전히 browserify를 사용하려는 누군가에게 유용 할 수 있습니다. 나를 위해 더 이상 필요는 없지만 어쨌든 귀하의 답변에 감사드립니다 (:
Totty.js

6
메인이 프로젝트의 루트에 있다면 :)
Alexander Mills

12
이 솔루션은 코드가 Mocha test와 같은 단위 테스트로 커버 된 경우 작동하지 않습니다.
alx lark

129

Browserify 핸드북 에는 정말 흥미로운 섹션이 있습니다 .

../../../../../../ .. 피하기

응용 프로그램의 모든 것이 공용 npm에 올바르게 속하는 것은 아니며 개인 npm 또는 git repo 설정의 오버 헤드는 여전히 많습니다. ../../../../../../../상대 경로 문제 를 피하기위한 몇 가지 방법이 있습니다.

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을 작성해야 합니다. 이렇게하면 응용 프로그램의 구성 변경에 대해 모듈이 더욱 강력 해지며 응용 프로그램 외부에서 패키지를 독립적으로 재사용하기가 더 쉬워집니다.

심볼릭 링크

심볼릭 링크를 만들 수 있고 창을 지원할 필요가없는 응용 프로그램에서 작업하는 경우 유용한 또 다른 방법은 a lib/ 또는 app/폴더 를에 심볼릭 링크하는 것 node_modules입니다. 프로젝트 루트에서 다음을 수행하십시오.

ln -s ../lib node_modules/app

이제 프로젝트에서 어디에서 당신의 파일을 필요로 할 수 있습니다 lib/수행하여 require('app/foo.js')얻을 lib/foo.js.

맞춤 경로

$NODE_PATH 환경 변수 사용에 대해 이야기 하거나 opts.pathsnode 및 browserify에 대한 디렉토리를 추가하여 모듈을 찾기 위해 어떤 장소를 이야기하는 것을 볼 수 있습니다 .

대부분의 다른 플랫폼과 달리, 쉘 디렉토리 형식의 경로 디렉토리를 $NODE_PATH사용하는 것은 node_modules디렉토리를 효과적으로 사용하는 것보다 노드에서 유리하지 않습니다 .

응용 프로그램이 런타임 환경 구성에 더 밀접하게 연결되어 있기 때문에 움직이는 부분이 많고 환경이 올바르게 설정된 경우에만 응용 프로그램이 작동하기 때문입니다.

노드와 브라우저는 모두 지원하지만 사용을 권장하지 않습니다 $NODE_PATH.


17
에 넣어의 유일한 아래쪽 node_modules폴더는 핵 (를 어렵게 만드는 것입니다 rm -rf node_modules폴더)
마이클

13
@Michael 그렇게 어렵지는 않습니다 : git clean -dx node_modules
Peter Wilkinson

3
또는 경우에 당신은 잊어 버린 git clean사람은 항상 수, 구문을 rm -rf node_modules && git checkout node_modules해야합니다 - git stash받는 어떤 변화가있는 경우 node_modules하위 디렉토리.
derenio

1
node_modules를 사용하는 아이디어가 마음에 들지만 소스 코드를 저장하는 것이 얼마나 휘발성인지 고려하지는 않습니다. 분리 된 모듈을 게시하고 원래 프로젝트에서 종속성으로 저장하는 것이 더 합리적이지 않습니까? node_modules 디렉토리의 변동성에 대한 명확한 솔루션을 제공하며 git, 기호 링크 또는 $ NODE_PATH 솔루션에 의존하기보다는 npm에만 의존합니다.
케빈 코시 올

1
NODE_PATH는 갈 길처럼 보입니다. "환경이 올바르게 설정된 경우에만 응용 프로그램이 작동합니다"이것은 항상 사실입니다! 모든 파일에서 모든 가져 오기를 변경하는 것보다 환경 설정 (일반적으로 하나의 파일로)을 얻는 것이 쉽지 않습니까?
CpILL

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.jsrequire('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존재하는 각 디렉토리에 대해 노드는 먼저 필드가 존재 xyz/package.json하는지 확인 하기 위해 a 를 찾습니다 "main". 이 "main"필드는 require()디렉토리 경로 인 경우 어떤 파일을 담당해야하는지 정의 합니다.

예를 들어, if /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
모듈로드 할 때 작동 방법에 대한 좋은 설명
goenning

2
이것은 매우 우아한 솔루션이며 위 답변의 모든 문제를 피합니다. 대답을 고려해야합니다, imho.
rodurico

38

큰 그림

"정말 나쁘다"지만 시간을 줘. 사실 정말 좋습니다. 명시 적 기능 require()은 프로젝트 수명주기 동안 신선한 공기를 마시는 것과 같은 전체 투명성과 이해의 용이성을 제공합니다.

이런 식으로 생각하십시오. 예를 읽고, 발가락을 Node.js에 담그고 "실제로 나쁜 IMO"라고 결정했습니다. Node.js 커뮤니티의 리더는 누구보다 Node.js 애플리케이션을 작성하고 유지 보수하는 데 더 많은 시간을 투자 한 사람들입니다. 저자가 신참 실수를했을 가능성은 무엇입니까? (그리고 나는 루비와 파이썬 배경에서 처음에는 재앙처럼 보인다는 것에 동의합니다.)

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('../../')

이제 해당 파일을 재배치 할 때 최악의 경우 하나의 모듈을 수정하는 것 입니다.


14
Node.js 직원이 이유를 위해 상대적 요구를 선택했음을 동의합니다. 나는 당신의 대답에서도 그 장점을 볼 수 없습니다. 그것은 여전히 ​​나에게 "나쁜"느낌;)
Adam Schmideg

21
“당신은 Node.js 커뮤니티의 두 번째 추측 지도자입니다.”– 같은 지도자들이 미래 / 약속 대신 콜백을 사용하기로 결정했습니다. 대부분의 nodejs 컨설팅에는 "리더"를 저주하고 사람들이 JVM으로 이동하도록 설득하는 것이 포함됩니다. nodejs를 사용하여 몇 개월이 지나면 훨씬 쉽습니다.
David Sergey

8
@nirth, JVM으로 이동 하시겠습니까? 하느님을 위해서 왜?
Ivancho

31
"당신은 Node.js 커뮤니티의 두 번째 추측 지도자입니다"라는 생각을 방해하는 말을 피하십시오.
atlex2

15
젠장, 그는 두 번째 추측 노드 리더입니다. 그것이 업계가 진행되는 방식입니다. 노드 사람들이 스레드 기반 동시성 모델을 제안한 리더를 다시 추측하지 않으면 노드가 없을 것입니다.
d512

20

node-rfr을 살펴보십시오 .

다음과 같이 간단합니다.

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

두 번째 줄은 var myModule = rfr ( '/ projectSubDir / myModule')이어야한다고 생각합니다.
Sikorski

1
문서에서 : var module2 = rfr ( 'lib / module2'); // 슬래시를 생략 할 수 있습니다.
igelineau

나는 그것을 시도하고 rfr은 노드와 함께 실행되도록 작동하지만 VS 코드로 코드 탐색을 중단합니다 ... VS에서 자동 완성을 사용할 수있는 해결 방법을 찾지
못했습니다

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

IMHO의 가장 쉬운 방법은 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');


@ 토티, 나는 당신이 의견에 설명 된 경우에 작동 할 수있는 다른 솔루션을 생각해 냈습니다. 테스트 프로젝트의 구조를tl;dr 가진 그림을 더 잘 보여줄 수 있습니다 .


글쎄, 지금까지 이것이 최선의 방법 인 것 같습니다. GLOBAL.requires = require ( 'r'). r; 내 index.js 파일에서. 그러나 내 서약 테스트에 문제가 있습니다. index.js를 실행하지 않으므로 요구 사항이 정의되지 않았기 때문에 테스트에 실패합니다. 어쨌든 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 2016 년

@Totty, 필요로하는 아무 문제 prj/some에서 prj/other(단지 테스트 require('prj/some'). 앱의 공통 모듈 (예 : 데이터베이스 계층)이 모두 갈 수 있습니다. 당신의 위치가 다르지 않을 것 lib입니다. 그것이 맞는지보십시오.
Aleksei Zabrodskii 2016 년

yest, 나는 그것을 업데이트했습니다 github.com/totty90/production01_server/tree/master/node_modules/... 큰했다. 그러나 node_modules를 사용하지 않고 모든 파일을 한 수준 위로 올릴 수 있습니까?
Totty.js 2016 년

12

process.cwd()내 프로젝트에 사용 합니다. 예를 들면 다음과 같습니다.

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

require아직이 문제 에 직면하지는 않았지만 이것이 절대 경로를 초래할 것이라는 점에 주목할 가치가 있습니다 .


1
CWD가 응용 프로그램이 저장된 디렉토리와 같을 필요는 없기 때문에 나쁜 생각입니다.
jiwopene

11

이 문제에 대한 좋은 토론이 여기에 있습니다 .

나는 동일한 아키텍처 문제에 부딪쳤다. 애플리케이션없이 더 많은 조직과 내부 네임 스페이스를 제공하는 방법을 원했다.

  • 외부 종속성과 응용 프로그램 모듈을 혼합하거나 응용 프로그램 별 코드를 위해 전용 npm repos를 방해
  • 리팩토링 및 이해를 어렵게하는 상대적 요구 사항 사용
  • 심볼릭 링크를 사용하거나 노드 경로를 변경하여 소스 위치를 숨길 수 있으며 소스 제어를 잘 수행하지 못함

결국 디렉토리가 아닌 파일 이름 지정 규칙을 사용하여 코드를 구성하기로 결정했습니다. 구조는 다음과 같습니다.

  • 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

파일을 다른 "폴더"로 "이동"하면 이름이 바뀌므로 파일을 이동하는 것보다 훨씬 쉽습니다. 또한 프로젝트에서 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 아니오 그것은 단지 필요한 파일과 관련이 있습니다.
protometa

8

나는 많은 솔루션을 시도했다. 나는 이것을 메인 파일 (예 : index.js)의 맨 위에 추가했다.

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

스크립트가로드 될 때 프로젝트 루트가 NODE_PATH에 추가됩니다. 이 프로젝트 루트에서 상대 경로를 참조하여 프로젝트의 파일을 요구할 수 있습니다 var User = require('models/user'). 이 솔루션은 프로젝트에서 다른 것을 실행하기 전에 프로젝트 루트에서 기본 스크립트를 실행하는 한 작동합니다.


8

대답 중 일부는 패키지로 node_module에 코드를 추가하는 가장 좋은 방법이라고 말합니다. 필자는 아마도 ../../../요구 를 잃을 수있는 가장 좋은 방법 이지만 실제로는 그렇게 할 수있는 방법을 제공하지 않습니다.

버전 2.0.0에서 로컬 파일에서 패키지를 설치할 수 있습니다. 즉, 루트에 원하는 모든 패키지가있는 폴더를 만들 수 있습니다.

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

따라서 package.json에서 다음 과 같이 외부 서버를 게시하거나 사용하지 않고 패키지로 modules(또는 foobar)을 추가 할 수 있습니다 .

{
  "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 설치가 필요한 테스트를 작성하는 데 도움이되지만 공개 레지스트리에 패키지를 공개 할 때는 사용하지 않아야합니다."
Ryan Smith

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);

어디에서든 루트에서 무언가를 원할 때마다 바닐라가 아닌 requireFromRoot를 사용하면됩니다. 지금까지 꽤 잘 작동합니다.


감사! 나는 이것이 꽤 똑똑하고 간단하다고 생각합니다.
Ryan

내가 죄를 지었으므로 아버지를 용서하십시오. 이것을 ES6에 포팅하고 다음을 얻었습니다 requireFromRoot = ((root) => (resource) => require(`${root}/${resource}`))(__dirname);. 솔루션을 좋아하지만 실제로 __dirname을 바인딩해야합니까?
Nuck

1
내 메모리는 이것에 약간 흐릿하지만 __dirname은 사용되는 파일에 따라 값이 변경된다고 생각합니다. 이제 함수가 단일 위치에 정의되어 있지만 여러 위치에서 사용되기 때문에이 바인딩이 없어도 값은 일정하게 유지되지만 실제로는 사실임을 보장하기 위해 수행했습니다.
user1417684

오래 전에이 작업을 수행하여 환경 테스트 등에 어려움을 겪습니다. 오버 헤드 가치가 없습니다. 무작위 새로운 세계는 새로운 사람들을 불확실하게 만듭니다 bla bla
The Dembinski

그리고 어떻게이 require기능을 수행합니까?
Darko Maksimovic

5

6 개월 이상 제가하고있는 실제 방법은 다음과 같습니다. node_modules라는 폴더를 프로젝트의 루트 폴더로 사용합니다.이 방법으로 절대 요구 사항이라고 부르는 모든 곳에서 항상 해당 폴더를 찾습니다.

  • node_modules
    • myProject
      • 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공급 업체가 있습니다.
마리우스 발치 티스

33
IMHO node_modules 폴더는 node_modules 전용입니다. 전체 프로젝트를 해당 폴더에 넣는 것은 좋지 않습니다.
McSas

2
@McSas 위와 동일한 효과를 얻는 대안으로 무엇을 제안 하시겠습니까?
spieglio

3
@cspiegl NODE_PATH환경 변수를 사용할 수 있습니다
Christopher Tarquini

5

이를 달성하는 가장 쉬운 방법은 앱 시작시 node_modules/app또는 (또는 호출하는 모든 것)을 가리키는 심볼릭 링크를 만드는 것 ../app입니다. 그런 다음에 전화하면 require("app/my/module")됩니다. 모든 주요 플랫폼에서 심볼릭 링크를 사용할 수 있습니다.

그러나 여전히 npm을 통해 설치되는 더 작고 유지 관리 가능한 모듈로 자료를 분할해야합니다. git-url을 통해 개인 모듈을 설치할 수도 있으므로 하나의 단일 앱 디렉토리를 가질 이유가 없습니다.


Windows를 지원하려면 노드 및 OS에 대한 자세한 지식이 필요합니다. 오픈 소스 프로젝트의 광범위한 사용을 제한 할 수 있습니다.
Steven Vachon

일반적으로이 패턴은 대부분의 오픈 소스 프로젝트 인 라이브러리에 사용하지 않습니다. 그러나 npm 빌드 후크에서 이러한 심볼릭 링크를 만들 수 있으므로 사용자가 필요로하는 심층적 인 지식이 없습니다.
Johannes Ewald

물론 Windows의 Node.js는 기본적으로 심볼릭 링크를 지원하지 않습니다.
Steven Vachon

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.js의 속성에 값을 할당하고 필요한 것을 나타내는 메시지와 함께 exports호출 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 디렉토리에서 노드를로드하는 방법을 활용하는 것입니다.

모듈 "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';

표준 CLI 응용 프로그램을 사용하여 Angular 참조에 대해 간단히 가져 오기 src/app/my.service를 수행 할 수 있으며 typescript 파일에 대해 상대적이 아닌 가져 오기를 사용하도록 VSC를 구성 할 수도 있습니다.
플로피

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

패키지 파일이있는 중첩 된 디렉토리가있는 경우 각 디렉토리는 해당 패키지 내의 파일 만 필요로합니다. 그게 당신이 원하는 행동 아닌가요? 웹팩으로 테스트하지 않았습니다.
gafi

이것은 간단한 프로젝트에서 완벽하게 작동했으며 다른 답변보다 훨씬 쉽습니다.
byxor

2

그냥 후속 할 좋은 대답 에서 파올로 모레티 와 Browserify. 당신이 transpiler를 사용하는 (예를 들어, 바벨, 타이프 라이터) 및 소스에 대한 별도의 폴더와 같은 transpiled 코드가있는 경우 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 etc가 src디렉토리를 dist디렉토리 로 변환하도록 할 수 있습니다 .

심볼릭 링크

symlink를 사용하면 몇 가지 수준의 중첩을 제거 할 수 있습니다.

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

바벨을 가진주의 --copy는-파일--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되지만 babel은 더 이상 심볼릭 링크를 볼 수 없습니다.


고마워,하지만 나는이 마술을하지 않는 것이 좋습니다. 먼저 모든 가져 오기를 잃게되며 IDE에서 계산하지 않습니다. 흐름 유형과 같은 다른 도구를 사용하면 제대로 작동하지 않습니다.
Totty.js

실제로 흐름은 제 경우에는 효과가있는 것 같습니다. 솔루션은 표준 노드 모듈 해상도 모델과 심볼릭 링크에 의존하기 때문에 놀랍지 않습니다. 따라서 흐름과 같은 도구가 이해하는 것은 실제로 마술이 아닙니다. 그러나 IDE는 다릅니다.
user716468

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.. 

이 방법은 외부 라이브러리에도 적용되며 필요할 때마다 이름을 하드 코딩 할 필요는 없지만 내보내기는 컨텍스트를 예상하는 함수가 아니므로 특별한 처리가 필요합니다.

나중에 빈을 함수로 정의 할 수도 있습니다 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는 자신의 폴더를 모듈로 호출 할 수 있습니다.

이를 위해서는 다음이 필요합니다. global 및 app-module-path 모듈

여기서 "App-module-path"는 모듈이며 Node.js 모듈 검색 경로에 추가 디렉토리를 추가 할 수 있습니다. "global"은이 객체에 첨부 한 모든 항목이 앱의 모든 곳에서 사용 가능하다는 것입니다.

이제이 스 니펫을 살펴보십시오.

global.appBasePath = __dirname;

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

__dirname은 현재 노드의 실행중인 디렉토리입니다. 여기에 모듈 경로를 검색하기위한 고유 한 경로를 제공 할 수 있습니다.

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