Node.js nasıl mutlak gerektirir? (göreli yerine)


234

Dosyalarımı her zaman geçerli modülle değil, projemin kök dizininden talep etmek istiyorum.

Örneğin, https://github.com/visionmedia/express/blob/2820f2227de0229c5d7f28009aa432f9f3a7b5f9/examples/downloads/app.js satır 6'ya bakarsanız,

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

Bu gerçekten kötü IMO. Tüm örneklerimi sadece bir seviye daha köke yakınlaştırmak istediğimi düşünün. Bu imkansız olurdu, çünkü her örnekte 30'dan fazla örneği ve birçok kez güncellemem gerekecekti. Buna:

express = require('../')

Benim çözümüm kök tabanlı için özel bir duruma sahip olmak olacaktır: eğer bir dize $ ile başlıyorsa projenin kök klasörüne göredir.

Herhangi bir yardım takdir, teşekkürler

Güncelleme 2

Şimdi bir şekilde yazmanıza izin veren ve hem istemcide hem de sunucuda çalışan requir.js kullanıyorum. Require.js ayrıca özel yollar oluşturmanıza da olanak tanır.

Güncelleme 3

Şimdi webpack + gulp'a taşındım ve sunucu tarafında modülleri işlemek için gelişmiş gereksinim kullanıyorum. Buraya bakın gerekçe: http://hackhat.com/p/110/module-loader-webpack-vs-requirejs-vs-browserify/


Açık bir kök yolu sabiti / değişkeni kullanmaya karar verirseniz, bu yanıt bu işe yarar . Çözüm, kök yolunu belirlemek için küçük bir github modülü kullanır.
steampowered

Yanıtlar:


162

Ve ne hakkında:

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

Dosyayı ana js dosyasından gerekliymiş gibi gerektirir, bu nedenle ana js dosyanız projenizin kökünde olduğu sürece oldukça iyi çalışır ... ve bu takdir ettiğim bir şeydir.


Kötü bir fikir değil (: Daha sonra bir şekilde requir.main modülünüzde uygulamayı yeniden eşleştirmek için başka yöntemler tanımlayabilirsiniz. Sanırım daha sonra requir.main.req ('client / someMod') yapabilirsiniz. benim mevcut requirjs daha ayrıntılı olmak.Ayrıca ben de değer sanmıyorum çünkü ben de browserify sevmiyorum çünkü değişiklikler anında değil ve değişiklikleri özlüyor (çünkü benim kod tarayıcı ve node.js hem çalışması gerekir).
Totty.js

4
Çok ayrıntılı bulursanız .bind () kullanın: var rootReq = requir.bind (requir.main); rootReq ('./path/to/module');
cronvel

evet, bu hala istemci tarafı için browserify kullanmak isteyen biri için yararlı olabilir. Benim için artık gerek yok, ama yine de cevabınız için teşekkürler (:
Totty.js

6
ANA PROJENİN KÖKÜNDE İSE :)
Alexander Mills

12
Bu çözüm olmaz eser Mocha testi gibi birim testleri ile kaplı kod eğer
alx Tarlakuşum

129

Browserify El Kitabında gerçekten ilginç bir bölüm var :

kaçınmak ../../../../../../ ..

Bir uygulamadaki her şey genel npm'ye ait değildir ve özel bir npm veya git repo kurma yükü çoğu durumda hala oldukça büyüktür. İşte ../../../../../../../göreli yollar probleminden kaçınmak için bazı yaklaşımlar .

node_modules

İnsanlar bazen uygulamaya özgü modülleri node_modules'e koymaya itiraz ederler, çünkü npm'den üçüncü taraf modüllerini de kontrol etmeden dahili modüllerinizi nasıl kontrol edeceğiniz açık değildir.

Cevap oldukça basit! .gitignoreYok sayılan bir dosyanız varsa node_modules:

node_modules

!Dahili uygulama modüllerinizin her biri için bir istisna ekleyebilirsiniz :

node_modules/*
!node_modules/foo
!node_modules/bar

Üst öğe yoksayılmışsa, bir alt dizinin işaretini kaldıramayacağınızı lütfen unutmayın . Bu nedenle, yoksaymak yerine, içeridekinode_modules her dizini hile ile yok saymanız gerekir ve daha sonra istisnalarınızı ekleyebilirsiniz. node_modulesnode_modules/*

Şimdi her yerde uygulamanızda size mümkün olacak require('foo') ya require('bar')çok büyük ve kırılgan göreli yolu kalmadan.

Çok fazla modülünüz varsa ve bunları npm tarafından yüklenen üçüncü taraf modüllerden daha ayrı tutmak istiyorsanız, hepsini aşağıdaki node_modulesgibi bir dizinin altına koyabilirsiniz node_modules/app:

node_modules/app/foo
node_modules/app/bar

Artık uygulamanızın herhangi bir yerine require('app/foo')veya require('app/bar')herhangi bir yerden erişebileceksiniz.

Bölümünde .gitignore, aşağıdakiler için bir istisna ekleyin node_modules/app:

node_modules/*
!node_modules/app

Başvurunuz dönüşümleri package.json yapılandırılan olsaydı, sen kendi dönüşümü alanında ayrı bir package.json oluşturmanız gerekir sizin node_modules/fooveyanode_modules/app/foo modül sınırları boyunca geçerli olmadığından bileşen dizininizde . Bu, modüllerinizi uygulamanızdaki yapılandırma değişikliklerine karşı daha sağlam hale getirecek ve paketleri uygulamanız dışında bağımsız olarak yeniden kullanmak daha kolay olacaktır.

Sembolik bağ

Symlinks yapabileceğiniz ve pencereleri desteklemeniz gerekmeyen bir uygulama üzerinde çalışıyorsanız başka bir kullanışlı hile, bir lib/ veya app/klasörü symlink etmektir node_modules. Proje kökünden şunları yapın:

ln -s ../lib node_modules/app

ve şimdi projenizde her yerde sizi dosyaları gerektiren mümkün olacak lib/yaparak require('app/foo.js')almaklib/foo.js .

özel yollar

Bazı yerlerin $NODE_PATH ortam değişkenini kullanma hakkında konuştuğunu veya opts.pathsdüğüm ve dizin bulmak için dizinler eklemek üzere dizinler eklemeyi görebilirsiniz.

Diğer birçok platformdan farklı $NODE_PATHolarak, düğüm dizinlerinde kabuk stili bir dizin dizisi kullanmak, node_modulesdizinde etkili bir şekilde kullanılmaya kıyasla düğümde uygun değildir .

Bunun nedeni, uygulamanızın bir çalışma zamanı ortam yapılandırmasına daha sıkı bağlanmasıdır, bu nedenle daha fazla hareketli parça vardır ve uygulamanız yalnızca ortamınız doğru bir şekilde kurulduğunda çalışır.

node ve browserify her ikisi de kullanımını destekler, ancak kullanımını engeller $NODE_PATH.


17
node_modulesKlasöre koymanın tek tarafı, nuke ( rm -rf node_modules) klasörünü zorlaştırmasıdır
Michael

13
@Michael O kadar zor değil: git clean -dx node_modules
Peter Wilkinson

3
Ya da git cleansözdizimini unuttuysanız, her zaman olabilir rm -rf node_modules && git checkout node_modules- alt dizinlerde git stashherhangi bir değişiklik olması durumunda emin olun node_modules.
derenio

1
Düğüm_modülleri kullanma fikrini seviyorum, ancak ne kadar uçucu olabileceğini düşünerek kaynak kodunu saklamak için değil. Ayrılan modülü yayınlamak ve orijinal projeye bağımlılık olarak kaydetmek daha anlamlı olmaz mıydı? Node_modules dizininin oynaklığına açık bir çözüm sağlar ve git, sembolik bağlantılar veya $ NODE_PATH çözümüne güvenmek yerine yalnızca npm'ye dayanır.
Kevin Koshiol

1
NODE_PATH gidilecek yol gibi görünüyor. "uygulamanız yalnızca ortamınız doğru kurulduğunda çalışır" bu her zaman doğrudur! Ortam kurulumunu (genellikle tek bir dosyada) almak, her dosyadaki her içe aktarmayı değiştirmekten daha kolay değil mi?
CpILL

73

node_modulesPaylaşılan kod için yeni bir klasör yapmak istiyorum , daha sonra düğüm izin ve en iyi ne yapmak gerekir.

Örneğin:

- node_modules // => these are loaded from your package.json
- app
  - node_modules // => add node-style modules
    - helper.js
  - models
    - user
    - car
- package.json
- .gitignore

Örneğin, sen eğer car/index.jsyapabilirsiniz require('helper')ve düğüm bulacaksınız!

Node_modules nasıl çalışır?

düğüm, rakip platformlar arasında benzersiz olan modülleri çözmek için akıllı bir algoritmaya sahiptir.

Eğer varsa require('./foo.js')dan /beep/boop/bar.js, düğüm arayacaktır ./foo.jsiçinde /beep/boop/foo.js. İle başlayan ./veya ../her zaman çağıran dosya için yerel olan yollar require().

Eğer gibi olmayan bir nispi adı gerektirdiğini ancak require('xyz')gelen /beep/boop/foo.jsdüğüm aramalarda, sırayla bu yolları, ilk maçında durdurma ve hiçbir şey bulunursa, hata yükseltme:

/beep/boop/node_modules/xyz
/beep/node_modules/xyz
/node_modules/xyz

Varolan her xyzdizin için, düğüm önce xyz/package.jsonbir "main"alan olup olmadığını görmek için a arar . "main"Hangi dosya alan tanımlar eğer ücret almalırequire() dizin yolu.

Örneğin /beep/node_modules/xyz, ilk eşleşme ise ve aşağıdakilere /beep/node_modules/xyz/package.jsonsahipse:

{
  "name": "xyz",
  "version": "1.2.3",
  "main": "lib/abc.js"
}

o zamandan gelen ihracat /beep/node_modules/xyz/lib/abc.jsiade edilecektir require('xyz').

Alan yoksa package.jsonveya "main"alan yoksa index.js, varsayılır:

/beep/node_modules/xyz/index.js

2
bir modül yüklerken nasıl çalıştığına dair harika bir açıklama
Goenning

2
Bu çok zarif bir çözümdür, yukarıdaki cevaplardaki tüm sorunları önler. Cevap düşünülmeli, imho.
rodurico

38

Büyük resim

"Gerçekten kötü" görünüyor ama zaman tanıyın. Aslında, gerçekten çok iyi. Açık olanlar require(), bir proje yaşam döngüsü sırasında temiz bir nefes almak gibi bir toplam şeffaflık ve anlayış kolaylığı sağlar.

Şöyle düşünün: Parmaklarınızı Node.js'ye daldırarak bir örnek okuyorsunuz ve "gerçekten kötü IMO" olduğuna karar verdiniz. Node.js topluluğunun, tahmini olarak herkesten daha fazla Node.js uygulaması yazmak ve bakımını yapmak için saatlerce oturum açan kişiler olan ikinci tahmin liderisiniz. Yazarın böyle bir çaylak hatası yapma şansı nedir? (Ve katılıyorum, Ruby ve Python geçmişimden, ilk başta bir felaket gibi görünüyor.)

Node.js'yi çevreleyen çok fazla hype ve counter-hype var. Ancak toz çöktüğünde, açık modüllerin ve "önce yerel" paketlerin benimsenmenin önemli bir itici gücü olduğunu kabul edeceğiz.

Ortak dava

Tabii ki, node_modulesgeçerli dizinden sonra ebeveyn, sonra büyükbaba veya büyükanne, büyükbaba veya büyükanne, vb. Böylece , kurduğunuz paketler zaten bu şekilde çalışıyor. Genellikle require("express")projenizin herhangi bir yerinden yapabilirsiniz ve iyi çalışıyor.

Kendinizi projenizin kökünden ortak dosyalar yüklüyorsanız (belki de ortak yardımcı işlevler oldukları için), o zaman bir paket yapmanın zamanı geldiğine dair büyük bir ipucu. Paketler çok basit: dosyalarınızı taşımak node_modules/ve bir koyun package.json oraya. İşte bu kadar! Bu ad alanındaki her şeye tüm projenizden erişilebilir. Paketler, kodunuzu genel bir ad alanına almanın doğru yoludur.

Diğer geçici çözümler

Ben şahsen bu teknikleri kullanmıyorum, ama sorunuza cevap veriyorlar ve tabii ki kendi durumunuzu benden daha iyi biliyorsunuz.

$NODE_PATHProje köküne ayarlayabilirsiniz . Bu dizin siz arandığında aranacaktır require().

Ardından, tüm örneklerinizden ödün verebilir ve ortak, yerel bir dosya isteyebilirsiniz. Bu ortak dosya, büyükbaba veya büyükanne dizinindeki gerçek dosyayı yeniden dışa aktarır.

örnekler / indirmeler / app.js (ve diğerleri gibi)

var express = require('./express')

örnekler / downloads / express.js

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

Şimdi bu dosyaları yeniden konumlandırdığınızda, en kötü durum bir dolgu modülünü düzeltmektir .


14
Node.js adamlarının bir nedenden ötürü göreli bir gereksinim seçmiş olması gerektiğini kabul ediyorum. Avantajlarını göremiyorum, ne cevabınızdan. Hala bana "kötü" geliyor;)
Adam Schmideg

21
“Node.js topluluğunun ikinci tahmin liderisiniz” - Aynı liderler vadeli işlemler / vaatler yerine geri çağrılar kullanmaya karar verdiler. Nodejs danışmanlığımın çoğunluğu, "liderleri" lanetlemeyi ve insanları JVM'ye taşınmaya ikna etmeyi içerir. Düğümleri kullandıktan birkaç ay sonra çok daha kolay :)
David Sergey

8
@nirth, JVM'ye taşınsın mı? Tanrı aşkına, neden?
Ivancho

31
"Node.js topluluğunun ikinci tahmin liderisiniz" lütfen bu düşünce cesaret kırıcı tondan kaçının.
atlex2

15
Kahretsin, o ikinci tahmin düğümü lideridir. Endüstri bu şekilde ilerliyor. Düğüm adamları, iplik temelli eşzamanlılık modellerini destekleyen liderleri ikinci olarak tahmin etmezse, düğümümüz olmazdı.
d512

20

Düğüm-rfr'ye bir göz atın .

Bu kadar basit:

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

ikinci satır var olması gerektiğini düşünüyorum myModule = rfr ('/ projectSubDir / myModule');
Sikorski

1
Dokümanlardan: var module2 = rfr ('lib / module2'); // Öncü eğik çizgi atlanabilir.
15'te igelineau

Ben denedim ve rfr düğüm ile yürütmek için Tamam çalışıyor, ama VS Kod ile kod navigasyon tatili ... VS otomatik tamamlama kullanabilmek için, bir geçici çözüm bulamadım ...
Alex Mantaut

13

Eğer kullanıyorsanız iplik yerine NPM kullanabileceğiniz çalışma alanları .

Diyelim ki servicesdaha kolay olmasını istediğim bir klasörüm var :

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

İplik çalışma alanı oluşturmak için, package.jsoniçinde bir dosya oluşturun services folder:

{
  "name": "myservices",
  "version": "1.0.0"
}

Ana paketinizde.json ekleyin:

"private": true,
"workspaces": ["myservices"]

yarn installProjenin kökünden çalıştırın .

Ardından, kodunuzun herhangi bir yerinde şunları yapabilirsiniz:

const { myFunc } = require('myservices/foo')

gibi bir şey yerine:

const { myFunc } = require('../../../../../../services/foo')

6
Belki de bunun npm için değil, sadece iplik için çalıştığını açıklığa kavuşturmak bir fikirdir ? Muhtemelen npm için de işe yarayacağını düşündüm, bu yüzden biraz iplik kullanmayı denedikçe ne yaptığımı merak ettim. Aptalca bir varsayım olabilirdi, ama belki de sadece ben değilim.
ArneHugo

2
Açıklığa kavuşturmak için biraz düzenledim. Karışıklık için özür dilerim.
cyberwombat

12

IMHO, en kolay yolu kendi fonksiyonunuzu GLOBALnesnenin bir parçası olarak tanımlamaktır . projRequire.jsAşağıdaki içeriklerle projenizin kök dizininde oluşturun :

var projectDir = __dirname;

module.exports = GLOBAL.projRequire = function(module) {
  return require(projectDir + module);
}

requireProjeye özgü modüllerden herhangi birini ayarlamadan önce ana dosyanızda :

// init projRequire
require('./projRequire');

Bundan sonra benim için çalışıyor:

// main file
projRequire('/lib/lol');

// index.js at projectDir/lib/lol/index.js
console.log('Ok');


@Totty, yorumlarda açıkladığınız dava için işe yarayabilecek başka bir çözümle karşılaştım. Açıklama olacak tl;dr, bu yüzden test projemin yapısıyla bir resim göstermeliyim .


şimdiye kadar bunu yapmanın en iyi yolu gibi görünüyor. Ben: GLOBAL.requires = gerektirir ('r'). R; index.js dosyamda. Ancak yeminlerimde bir sorunum var, index.js'yi çalıştırmıyorlar, bu yüzden testlerim başarısız oluyor, çünkü requirS tanımsız. Neyse, şimdilik GLOBAL.requires = requir ('r') ekleyebilirim. her testin en üstünde. daha iyi bir fikrin var mı? github.com/totty90/production01_server/commit/…
Totty.js


"pathes-test / node_modules / other.js" içindeyim ve "pathes-test / node_modules / some.js" gerektiğinde sorun olur. Gereksinim yerine ('prj / some ") (' ./ some ') istemem gerekir. Ve bu şekilde tüm benim app node_modules dir olurdu?
Totty.js

@Totty gerektiren bir sorun prj/someile ilgili prj/other(sadece test require('prj/some'). Uygulamanızın ortak modüllerinin tümü oraya gidebilir (örneğin veritabanı katmanı). Diyelim ki, nerede olduğu fark etmez lib. Uygun olup olmadığını görmeye çalışın.
Aleksei Zabrodskii

evet, ben güncelledim: github.com/totty90/production01_server/tree/master/node_modules/… bu harika çalıştı. Ama node_modules kullanmadan tüm dosyalarımı bir seviye yukarı koyabilir miyim?
Totty.js

12

Kullandığım process.cwd()projelerimde. Örneğin:

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

Bu konuda requirekesin bir yolla sonuçlanacağımı belirtmek gerekir , ancak henüz bu konuda sorun yaşamamıştım.


1
Bu kötü bir fikir çünkü CWD, uygulamanın kaydedildiği dizinle aynı olmak zorunda değil.
jiwopene

11

Burada bu konuyla ilgili iyi bir tartışma var .

Aynı mimari problemle karşılaştım: Uygulamama daha fazla organizasyon ve dahili ad alanı vermenin bir yolunu istemek:

  • uygulama modüllerini harici bağımlılıklarla karıştırmak veya uygulamaya özel kod için özel npm depolarıyla uğraşmak
  • yeniden düzenleme ve kavrayışı zorlaştıran akraba gereksinimlerini kullanmak
  • sembolik noktalar kullanmak veya kaynak konumlarını gizleyebilen ve kaynak kontrolü ile iyi oynamamayan düğüm yolunu değiştirme

Sonunda, kodumu dizinler yerine dosya adlandırma kurallarını kullanarak düzenlemeye karar verdim. Bir yapı şöyle görünecektir:

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

Sonra kodda:

var app_config = require('./app.config');
var app_models_foo = require('./app.models.foo');

ya da sadece

var config = require('./app.config');
var foo = require('./app.models.foo');

ve harici bağımlılıklar node_modules'ten her zamanki gibi kullanılabilir:

var express = require('express');

Bu şekilde, tüm uygulama kodu hiyerarşik olarak modüller halinde düzenlenir ve uygulama köküne göre diğer tüm kodlar tarafından kullanılabilir.

Ana dezavantaj elbette bir dosya tarayıcısında, ağacı dizinler halinde organize edilmiş gibi genişletemez / daraltamazsınız. Ama tüm kodların nereden geldiğiyle ilgili çok açık olduğunu ve herhangi bir 'sihir' kullanmadığını seviyorum.


Bağladığınız özden, çözüm # 7, "Sarıcı" oldukça basit ve kullanışlıdır.
Pier-Luc Gendreau

Bir küçük kolaylık daha görüyorum - bir dosyayı farklı "klasöre" taşımak "yeniden adlandırmaya dönüşüyor - dosyayı taşımaktan daha kolay. Ayrıca, proje üzerinde yarım saat çalıştıktan sonra, uygulama ağacımın hemen hemen hepsinin genişletildiğini fark ediyorum. 1 seviye klasör alanı eklemek, büyük kod tabanını yönetilebilir hale getirebilir ve ../x/xzaten okunabilir olan çok fazla tanıtılamaz .
Kayak

Düğümlerde belirgin bir eksikliğin üstesinden gelmek için eğik çizgiler yerine noktalar kullanarak klasörleri yeniden keşfediyorsunuz.
Simone Gianni

9

Proje kökünüzün geçerli çalışma dizini olduğu varsayıldığında, bunun çalışması gerekir:

// 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');de geçerlidir.
cespon

7
@cespon no, sadece gereken dosyaya göredir.
protometa

8

Bu çözümlerin çoğunu denedim. Ben ana dosya (örn. İndex.js) üstüne ekleyerek sona erdi:

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

Bu, komut dosyası yüklendiğinde proje kökünü NODE_PATH öğesine ekler. Projemdeki herhangi bir dosyayı, proje kökünden göreli yoluna başvurarak istememe izin verir var User = require('models/user'). Bu çözüm, projenizde başka bir şey çalıştırmadan önce proje kökünde bir ana komut dosyası çalıştırdığınız sürece çalışmalıdır.


8

Bazı cevaplar en iyi yolu kod olarak bir paket olarak node_module eklemek olduğunu söylüyor, katılıyorum ve muhtemelen ../../../içinde kaybetmek için en iyi yolu gerektirir ama hiçbiri aslında bunu yapmak için bir yol vermek.

sürümden 2.0.0yerel dosyalardan bir paket yükleyebilirsiniz, yani kökünüzde istediğiniz tüm paketlerle klasör oluşturabilirsiniz,

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

yani package.json'da modules(veya foove bar) yayınlamadan veya şu şekilde harici bir sunucu kullanmadan paket olarak ekleyebilirsiniz :

{
  "name": "baz",
  "dependencies": {
    "bar": "file: ./modules/bar",
    "foo": "file: ./modules/foo"
  }
}

Bundan sonra , diğer tüm paketlerde yaptığınız gibi npm install, koda ile erişebilirsiniz var foo = require("foo").

Daha fazla bilgi burada bulunabilir :

https://docs.npmjs.com/files/package.json#local-paths

ve burada bir paket nasıl oluşturulur:

https://docs.npmjs.com/getting-started/creating-node-modules


1
"Bu özellik, yerel çevrimdışı geliştirme ve harici bir sunucuya çarpmak istemediğiniz yerlerde npm kurulumu gerektiren, ancak paketleri genel kayıt defterine yayınlarken kullanılmaması gereken testler oluşturmak için yararlıdır."
Ryan Smith

7

Yaptığım bir modülü kullanabilirsiniz, Undot . Gelişmiş bir şey değildir, sadece bir yardımcıdır, böylece bu nokta cehennemini basitçe önleyebilirsiniz.

Misal:

var undot = require('undot');
var User = undot('models/user');
var config = undot('config');
var test = undot('test/api/user/auth');

6

App.js dosyanızda böyle bir şey tanımlayabilirsiniz:

requireFromRoot = (function(root) {
    return function(resource) {
        return require(root+"/"+resource);
    }
})(__dirname);

ve daha sonra kökünden bir şey istemek istediğinizde, nerede olursanız olun, vanilya gereksinimi yerine requirFromRoot'u kullanırsınız. Şimdiye kadar benim için oldukça iyi çalışıyor.


Teşekkürler! Bence bu oldukça akıllı ve anlaşılır.
Ryan

Affet beni baba, çünkü günah işledim. Ben ES6 bu taşıdık ve aşağıdakileri var: requireFromRoot = ((root) => (resource) => require(`${root}/${resource}`))(__dirname);. Çözümü seviyorum, ama __dirname'i gerçekten böyle mi bağlamanız gerekiyor?
Nuck

1
Hafızam bu konuda biraz puslu, ama __dirname içinde kullanılan dosyaya bağlı olarak değeri değiştirdiğine inanıyorum. Şimdi, fonksiyon tek bir yerde tanımlandığı, ancak birden fazla yerde kullanıldığı için, değerin bu bağlanma olmadan bile sabit kalacağı, ancak bunun aslında böyle olmasını sağlamak için yaptım.
user1417684

bunu uzun zaman önce yaptı, env ve benzerlerini test etmede acılara neden oldu. yükü değmez. rastgele yeni küresel yeni insanlar belirsiz bla bla yapar
The Dembinski

Ve requirebu işlevi nasıl yapıyorsunuz ?
Darko Maksimovic

5

İşte 6 aydan daha uzun bir süredir yaptığım gerçek. Projede kök klasörüm olarak node_modules adlı bir klasör kullanıyorum, bu şekilde her zaman mutlak bir gereksinim olarak adlandırdığım her yerden o klasörü arayacaktır:

  • node_modules
    • Projem
      • index.js ("./ someFolder / hey.js") yerine zorunlu ("myProject / someFolder / hey.js") isteyebilirim.
      • hey.js içeren someFolder

Bu, klasörlere iç içe yerleştirdiğinizde daha kullanışlıdır ve mutlak şekilde ayarlanmışsa bir dosya konumunu değiştirmek çok daha az iştir. Tüm uygulamamda sadece 2 göreceli gereksinimi kullanıyorum .


4
Ben yerel (proje) 'ın eklemek dışında benzer bir yaklaşım kullanmak node_modulesiçinde /srcve ayrılmak /node_modulesşeyler ayrı tutmak için satıcılar için. Bu yüzden /src/node_modulesyerel kod ve /node_modulessatıcılar için var.
Marius Balčytis

33
IMHO node_modules klasörü yalnızca node_modules içindir. Tüm projenizi bu klasörün içine koymak iyi bir uygulama değildir.
McSas

2
@McSas Yukarıdaki ile aynı etkiyi elde etmek için alternatif olarak ne önerirsiniz?
Ocak'ta spieglio

3
@cspiegl NODE_PATHOrtam değişkenini kullanabilirsiniz
Christopher Tarquini

5

Bunu başarmanın en kolay yolu, uygulama başlangıcında node_modules/app(veya her ne derseniz) işaret eden bir sembolik bağlantı oluşturmaktır ../app. Sonra sadece arayabilirsiniz require("app/my/module"). Sembolik bağlantılar tüm büyük platformlarda mevcuttur.

Bununla birlikte, öğelerinizi yine de npm ile kurulan daha küçük, bakımı kolay modüllere bölmelisiniz. Özel modüllerinizi git-url aracılığıyla da yükleyebilirsiniz, bu nedenle tek bir monolitik uygulama dizinine sahip olmanız için bir neden yoktur.


Windows desteği, Düğüm ve işletim sistemi hakkında daha ayrıntılı bilgi gerektirir. Açık kaynaklı bir projenin yaygın kullanımını sınırlayabilir.
Steven Vachon

Genellikle bu modeli bir kütüphane için kullanmam (çoğu açık kaynaklı projedir). Bununla birlikte, bu sembolik bağları npm yapı kancasında oluşturmak mümkündür, böylece kullanıcı tarafından gereken derinlemesine bilgi yoktur.
Johannes Ewald

Elbette, ancak Windows'ta Node.js varsayılan olarak sembolik bağlantıları desteklemez.
Steven Vachon

4

Kendi projenizde, kök dizinde kullanılan herhangi bir .js dosyasını değiştirebilir ve yolunu process.envdeğişkenin bir özelliğine ekleyebilirsiniz . Örneğin:

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

Daha sonra tesise her yerden erişebilirsiniz:

// in app.js
express = require(process.env.root);

4

Başka bir cevap:

Bu klasörlerin yapısını düşünün:

  • node_modules
    • lodash
  • src
    • altdiz
      • foo.js
      • bar.js
    • main.js
  • testler

    • test.js

Daha sonra test.js'de , aşağıdaki gibi dosyalara ihtiyacınız vardır:

const foo = require("../src/subdir/foo");
const bar = require("../src/subdir/bar");
const main = require("../src/main");
const _ = require("lodash");

ve main.js'de :

const foo = require("./subdir/foo");
const bar = require("./subdir/bar");
const _ = require("lodash");

Artık babel ve babel-plugin-module-resolver'ı bununla kullanabilirsiniz. 2 kök klasörü yapılandırmak için babelrc dosyası:

{
    "plugins": [
        ["module-resolver", {
            "root": ["./src", "./src/subdir"]
        }]
    ]
}

Artık testlerde ve src'de aynı şekilde dosyalara gereksinim duyabilirsiniz :

const foo = require("foo");
const bar = require("bar");
const main = require("main");
const _ = require("lodash");

ve es6 modülü sözdizimini kullanmak istiyorsanız :

{
    "plugins": [
        ["module-resolver", {
            "root": ["./src", "./src/subdir"]
        }],
        "transform-es2015-modules-commonjs"
    ]
}

daha sonra testleri ve src'deki dosyaları aşağıdaki gibi içe aktarırsınız :

import foo from "foo"
import bar from "bar"
import _ from "lodash"

4

Az önce app-module- path'den bahseden bu makaleye rastladım . Bu gibi bir temel yapılandırmanıza izin verir:

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

3

Could examplesdizin içermesi node_modulesprojenin köküne sembolik bağlantı ile project -> ../../böylece kullanımına örnekler izin require('project')bu eşleştirmeyi kaldırmaz rağmen, kaynak kullanmasına izin vermez, require('project')yerine require('../../').

Bunu test ettim ve v0.6.18 ile çalışıyor.

Arasında Listeleme projectdizinine:

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

İçerikleri, index.jsatar bir özelliği bir değer exportsnesne ve çağrıştırır console.loggerekli olan bildiren bir mesaj ile. İçeriği test.jsDİR require('project').


testinizin kaynak kodunu gösterebilir misiniz lütfen? Peki, ve bu şekilde ('project.a') bu şekilde ihtiyaç duymam gerekirse işe yarar mı?
Totty.js

Ne demek istiyorsun require('project.a')? Bunu demek olabileceğini düşünüyorum require('project/a')rağmen require('project').ade mümkündür?
Dan D.

ancak örneğinizle, gerektiren yöntem gerektiren bir modülün bulunduğu her klasörde bu klasörleri oluşturmanız gerekir. Her neyse, klasöre bağlı olarak "../" zamanlarına dikkat etmeniz gerekir.
Totty.js

Aslında bağlantının yalnızca node_modulesdosyanın en yakın üst öğesindeki bir dizinde olması gerekir ve bağlantının her ikisi için de aynı olması gerekir. Bkz. Nodejs.org/api/…
Dan D.

Ve o yerden göreceli olur. Örneğin: project/node_modules/project -> ../.
Dan

2

Herkes bu sorunu aşmak için başka bir yol arıyor, işte benim kendi katkısı:

https://www.npmjs.com/package/use-import

Temel fikir: projenin kökünde dosya yollarınızı kısayol adlarıyla eşleyen bir JSON dosyası oluşturursunuz (veya bunu sizin için yapmak için use-automapper'ı alırsınız). Daha sonra bu adları kullanarak dosyalarınızı / modüllerinizi isteyebilirsiniz. Şöyle ki:

var use = require('use-import');
var MyClass = use('MyClass');

İşte bu.


2

Ne yapmak istiyorum nasıl düğüm node_module dizininden bunun için yükler kaldıraç olduğunu.

Biri "şey" modülünü yüklemeye çalışırsa,

require('thing');

Düğüm daha sonra 'düğüm_modülü' dizininde 'şey' dizinini arayacaktır.

Node_module normalde projenin kökünde olduğundan, bu tutarlılığı kaldırabiliriz. (Node_module kökte değilse, başa çıkabileceğiniz başka baş ağrılarınız da vardır.)

Eğer dizine girip sonra dışarı çıkarsak, düğüm projesinin köküne tutarlı bir yol alabiliriz.

require('thing/../../');

Eğer / happy dizinine erişmek istersek bunu yapardık.

require('thing/../../happy');

Oldukça acayip olsa da, node_modules yükünün işlevselliğinin değişmesi durumunda hissediyorum, başa çıkmak için daha büyük sorunlar olacaktır. Bu davranış tutarlı olmalıdır.

Bir şeyleri açıklığa kavuşturmak için bunu yapıyorum, çünkü modülün adı önemli değil.

require('root/../../happy');

Son zamanlarda açısal2 için kullandım. Kökten bir hizmet yüklemek istiyorum.

import {MyService} from 'root/../../app/services/http/my.service';

Açısal referansınız hakkında, standart bir CLI uygulamasıyla, içe aktarabilirsiniz src/app/my.service, ayrıca VSC'yi daktilo dosyaları için göreceli olmayan içe aktarmaları kullanacak şekilde yapılandırabilirsiniz.
Ploppy

2

Global değişkenleri tanıtmadan veya düğüm varsayılanlarını geçersiz kılmadan, proje kökünden göreceli yollarına göre paketler gerektirmenizi sağlayan bu küçük paketi yazdım

https://github.com/Gaafar/pkg-require

Bu şekilde çalışır

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

Bazen ana projede özel paketlerim var, bu senaryo bununla kırılacak. Buna ek olarak, webpack ile iyi çalışacağından emin değilim (benim yaptığım gibi node.js ile webpack kullanmanız durumunda)
Totty.js

Paket dosyaları içeren iç dizinleriniz varsa, her dizin yalnızca paketinin içinde dosya gerektirebilir. İstediğiniz davranış bu değil mi? Webpack ile test etmedim.
gafi

Bu basit bir proje için mükemmel çalıştı ve diğer cevaplardan çok daha kolay.
byxor

2

Sadece takip etmek istiyorum harika cevap den Paolo Moretti ve Browserify. Eğer bir transpiler kullanırken (örneğin, babel, daktilo versiyonu) ve kaynak için ayrı klasörler ve benzeri transpiled kodunuz varsa src/ve dist/, sen çözümleri olarak bir varyasyonunu kullanabilirsiniz

node_modules

Aşağıdaki dizin yapısıyla:

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

daha sonra babel vs'nin srcdizini distdizine aktarmasına izin verebilirsiniz .

Sembolik bağ

Symlink kullanarak bazı iç içe yerleştirme düzeylerinden kurtulabiliriz:

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

Babel ile ilgili uyarı, --copy-dosyaları--copy-files bayrağı babeliyi sembolik ile uğraşmaz. ..Symlink'te gezinmeye ve sonsuz dosyaları tekrar tekrar görmeye devam edebilir . Geçici çözüm aşağıdaki dizin yapısını kullanmaktır:

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

Bu şekilde, altında kod srchala appçözülmüş olacak src, babil artık sembolik bağlantıları görmeyecekti.


Teşekkürler, ama bu sihri yapmayı tavsiye etmem. İlk önce tüm ithalatları kaybedeceksiniz, bunlar IDE'niz tarafından hesaplanmayacak. Akış tipi gibi başka araçlar kullanırsanız, düzgün çalışmaz.
Totty.js

Aslında akış benim durumumda çalışıyor gibi görünüyor, çünkü çözümler standart düğüm modülü çözünürlük modeline ve semboliklere bağlı olduğu için şaşırtıcı değil. Bu nedenle, akış gibi araçların anlaması gerçekten sihir değildir. Ancak IDE'ler farklıdır.
user716468

2

Herhangi bir seviyeden dosya gerektirmek için aynı sadeliği arıyordum ve modül takma adı buldum .

Sadece kur:

npm i --save module-alias

Package.json dosyanızı açın, burada yollarınız için takma adlar ekleyebilirsiniz, örn.

"_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
}

Ve takma adlarınızı basitçe kullanarak:

require('module-alias/register')
const deep = require('@deep')
const module = require('something')


1

Bu sorunu çözmek için yeni bir yol denemek üzereyiz.

Bahar ve guice gibi bilinen diğer projelerden örnekler alarak, tüm "zorunlu" ifadesini içeren bir "bağlam" nesnesi tanımlayacağız.

Bu nesne daha sonra kullanım için diğer tüm modüllere aktarılacaktır.

Örneğin

var context = {}

context.module1 = require("./module1")( { "context" : context } )
context.module2 = require("./module2")( { "context" : context } )

Bu, her modülü seçimler alan bir işlev olarak yazmamızı gerektirir, bu da bize en iyi uygulama olarak bakar.

module.exports = function(context){ ... }

ve sonra bir şey istemek yerine bağlama bakacaksınız.

var module1Ref = context.moduel1;

İsterseniz, gerekli ifadeleri yapmak için kolayca bir döngü yazabilirsiniz

var context = {};
var beans = {"module1" : "./module1","module2" : "./module2" }; 
for ( var i in beans ){
    if ( beans.hasOwnProperty(i)){
         context[i] = require(beans[i])(context);
    }
};

Bu, alay etmek istediğinizde (testler) hayatı kolaylaştırır ve kodunuzu bir paket olarak yeniden kullanılabilir hale getirirken sorununuzu yol boyunca çözer.

Ayrıca, fasulye bildirimini ondan ayırarak bağlam başlatma kodunu yeniden kullanabilirsiniz. örneğin, main.jsdosyanız böyle görünebilir

var beans = { ... }; // like before
var context = require("context")(beans); // this example assumes context is a node_module since it is reused.. 

Bu yöntem aynı zamanda harici kütüphaneler için de geçerlidir, her ihtiyacımız olduğunda isimlerini sabit kodlamaya gerek yoktur - ancak ihracatı bağlamı bekleyen fonksiyonlar olmadığından özel bir işlem gerektirecektir.

Daha sonra fasulyeleri require, çevreye göre farklı modüller oluşturmamıza izin veren fonksiyonlar olarak tanımlayabiliriz , ancak bu iş parçacığının kapsamı dışındadır.


1

Aynı sorunla ilgili sorun yaşıyordum, bu yüzden include adlı bir paket yazdım .

Package.json dosyanızı bularak projenizin kök klasörünü bulan tanıtıcıları dahil edin , ardından verdiğiniz yol bağımsız değişkenini tüm göreli yol karışıklığı olmadan yerel requir () öğesine iletir. Bunun, requir () yerine değil, paketlenmemiş / üçüncü taraf olmayan dosya veya kitaplıkların işlenmesini gerektiren bir araç olduğunu hayal ediyorum. Gibi bir şey

var async = require('async'),
    foo   = include('lib/path/to/foo')

Umarım faydalı olabilir.


1

Uygulamanızın giriş noktası js dosyası (aslında "düğüm" üzerinde çalıştırdığınız dosya) proje kök dizininizdeyse, bunu rootpath npm modülü ile kolayca yapabilirsiniz . Sadece üzerinden yükleyin

npm install --save rootpath

... sonra giriş noktası js dosyasının en üstüne şunu ekleyin:

require('rootpath')();

Bu noktadan sonra, tüm gerekli çağrılar artık proje köküne göredir - örneğin require('../../../config/debugging/log'); olur require('config/debugging/log');(yapılandırma klasörünün proje kökünde olduğu yer).


1

Basit satırlarda, kendi klasörünüzü modül olarak çağırabilirsiniz:

Bunun için ihtiyacımız var: global ve uygulama modülü yolu modülü

burada "App-module-path" modül, Node.js modül arama yoluna ek dizinler eklemenizi sağlar Ve "global", bu nesneye eklediğiniz her şey uygulamanızın her yerinde kullanılabilir olacaktır.

Şimdi bu snippet'e bir göz atın:

global.appBasePath = __dirname;

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

__dirname, düğümün geçerli çalışan dizinidir. Modül yolunu aramak için buraya kendi yolunuzu verebilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.