Ich möchte meine Dateien immer am Stamm meines Projekts und nicht relativ zum aktuellen Modul benötigen.
Wenn Sie sich beispielsweise https://github.com/visionmedia/express/blob/2820f2227de0229c5d7f28009aa432f9f3a7b5f9/examples/downloads/app.js Zeile 6 ansehen, sehen Sie
express = require('../../')
Das ist wirklich schlecht, IMO. Stellen Sie sich vor, ich möchte alle meine Beispiele nur um eine Ebene näher an die Wurzel bringen. Das wäre unmöglich, da ich mehr als 30 Beispiele und viele Male in jedem Beispiel aktualisieren müsste. Dazu:
express = require('../')
Meine Lösung wäre, einen Sonderfall für root zu haben: Wenn eine Zeichenfolge mit einem $ beginnt, ist sie relativ zum Stammordner des Projekts.
Jede Hilfe wird geschätzt, danke
Update 2
Jetzt verwende ich require.js, mit dem Sie auf eine Weise schreiben können und das sowohl auf dem Client als auch auf dem Server funktioniert. Mit Require.js können Sie auch benutzerdefinierte Pfade erstellen.
Update 3
Jetzt bin ich zu Webpack + Gulp gewechselt und verwende Enhanced-Require, um Module auf der Serverseite zu handhaben. Siehe hier die Begründung: http://hackhat.com/p/110/module-loader-webpack-vs-requirejs-vs-browserify/
Antworten:
Und was ist mit:
Es erfordert die Datei so, als ob sie aus der Haupt-JS-Datei benötigt würde, also funktioniert es ziemlich gut, solange sich Ihre Haupt-JS-Datei im Stammverzeichnis Ihres Projekts befindet ... und das weiß ich zu schätzen.
quelle
Es gibt einen wirklich interessanten Abschnitt im Browserify-Handbuch :
quelle
node_modules
Ordner ist, dass es schwieriger ist, den Ordner nuke (rm -rf node_modules
) zu erstellengit clean
Syntax vergessen haben , können Sie immerrm -rf node_modules && git checkout node_modules
- seien Sie sicher,git stash
falls sich Änderungen an dennode_modules
Unterverzeichnissen ergeben.Ich mag es, einen neuen
node_modules
Ordner für gemeinsam genutzten Code zu erstellen, dann Knoten und Anforderung das tun zu lassen, was er am besten kann.beispielsweise:
Zum Beispiel, wenn Sie in sind
car/index.js
, können Sierequire('helper')
und Knoten wird es finden!Funktionsweise von node_modules
Der Knoten verfügt über einen cleveren Algorithmus zum Auflösen von Modulen, der unter den Konkurrenzplattformen einzigartig ist.
Wenn Sie
require('./foo.js')
von kommen/beep/boop/bar.js
, sucht der Knoten nach./foo.js
in/beep/boop/foo.js
. Pfade, die mit einem./
oder beginnen,../
sind immer lokal für die aufrufende Dateirequire()
.Wenn Sie jedoch einen nicht relativen Namen wie
require('xyz')
from benötigen/beep/boop/foo.js
, durchsucht der Knoten diese Pfade der Reihe nach, stoppt bei der ersten Übereinstimmung und löst einen Fehler aus, wenn nichts gefunden wird:Für jedes vorhandene
xyz
Verzeichnis sucht der Knoten zuerst nach a,xyz/package.json
um festzustellen, ob ein"main"
Feld vorhanden ist. Das"main"
Feld definiert, welche Datei die Verantwortung übernehmen soll, wenn Sierequire()
den Verzeichnispfad angeben.Zum Beispiel, wenn
/beep/node_modules/xyz
es das erste Spiel ist und/beep/node_modules/xyz/package.json
hat:dann werden die Exporte von
/beep/node_modules/xyz/lib/abc.js
zurückgegeben vonrequire('xyz')
.Wenn kein
package.json
oder kein"main"
Feld vorhanden ist,index.js
wird angenommen:quelle
Das große Bild
Es scheint "wirklich schlecht", aber gib ihm Zeit. Es ist in der Tat wirklich gut. Die expliziten
require()
s bieten eine vollständige Transparenz und ein leichtes Verständnis, das wie ein Hauch frischer Luft während eines Projektlebenszyklus ist.Stellen Sie sich das so vor: Sie lesen ein Beispiel, tauchen Ihre Zehen in Node.js ein und haben entschieden, dass es "wirklich schlechte IMO" ist. Sie sind zweitwichtigste Anführer der Node.js-Community, Leute, die mehr Stunden als jeder andere protokolliert haben, um Node.js-Anwendungen zu schreiben und zu warten. Wie groß ist die Chance, dass der Autor einen solchen Anfängerfehler gemacht hat? (Und ich stimme zu, aus meinem Ruby- und Python-Hintergrund scheint es zunächst eine Katastrophe zu sein.)
Es gibt viel Hype und Gegenhype um Node.js. Wenn sich der Staub gelegt hat, werden wir anerkennen, dass explizite Module und "local first" -Pakete ein wesentlicher Treiber für die Einführung waren.
Der häufige Fall
Natürlich wird
node_modules
aus dem aktuellen Verzeichnis nach dem Elternteil, dann nach dem Großelternteil, dem Urgroßelternteil usw. gesucht. Von Ihnen installierte Pakete funktionieren also bereits auf diese Weise. Normalerweise können Sierequire("express")
von überall in Ihrem Projekt und es funktioniert gut.Wenn Sie häufig verwendete Dateien aus dem Stammverzeichnis Ihres Projekts laden (möglicherweise, weil es sich um allgemeine Dienstprogrammfunktionen handelt), ist dies ein wichtiger Hinweis darauf, dass es Zeit ist, ein Paket zu erstellen. Pakete sind sehr einfach: Verschieben Sie Ihre Dateien in
node_modules/
und legen Sie einepackage.json
dort ab. Voila! Auf alles in diesem Namespace kann von Ihrem gesamten Projekt aus zugegriffen werden. Pakete sind der richtige Weg, um Ihren Code in einen globalen Namespace zu bringen.Andere Problemumgehungen
Ich persönlich benutze diese Techniken nicht, aber sie beantworten Ihre Frage, und natürlich kennen Sie Ihre eigene Situation besser als ich.
Sie können
$NODE_PATH
Ihr Projektstammverzeichnis festlegen . Dieses Verzeichnis wird bei Ihnen durchsuchtrequire()
.Als nächstes könnten Sie eine gemeinsame lokale Datei für alle Ihre Beispiele kompromittieren und benötigen. Diese allgemeine Datei exportiert einfach die wahre Datei im Großelternverzeichnis erneut.
Beispiele / Downloads / app.js (und viele andere mögen es)
Beispiele / Downloads / express.js
Wenn Sie diese Dateien verschieben, wird im schlimmsten Fall das eine Shim- Modul repariert .
quelle
Schauen Sie sich node-rfr an .
So einfach ist das:
quelle
Wenn Sie Garn anstelle von npm verwenden , können Sie Arbeitsbereiche verwenden .
Angenommen, ich habe einen Ordner, den
services
ich einfacher benötigen möchte:Um einen Garnarbeitsbereich zu erstellen, erstellen Sie eine
package.json
Datei inservices folder
:Fügen Sie in Ihrem Hauptpaket.json Folgendes hinzu:
Führen Sie
yarn install
vom Stammverzeichnis des Projekts aus.Dann können Sie überall in Ihrem Code Folgendes tun:
statt so etwas wie:
quelle
IMHO ist der einfachste Weg, Ihre eigene Funktion als Teil des
GLOBAL
Objekts zu definieren . Erstellen SieprojRequire.js
im Stammverzeichnis Ihres Projekts den folgenden Inhalt:In Ihrer Hauptdatei, bevor
require
Sie eines der projektspezifischen Module verwenden:Danach funktioniert folgendes für mich:
@Totty, ich habe mir eine andere Lösung ausgedacht, die für den Fall funktionieren könnte, dass Sie in den Kommentaren beschrieben haben. Die Beschreibung wird sein
tl;dr
, also zeige ich besser ein Bild mit der Struktur meines Testprojekts .quelle
prj/some
vonprj/other
(nur getestetrequire('prj/some'
). Alle gängigen Module Ihrer App können dorthin gehen (z. B. Datenbankebene). Wird keinen Unterschied machen, wo Ihr, sagen wir,lib
ist. Versuchen Sie zu sehen, ob es passt.Ich benutze
process.cwd()
in meinen Projekten. Beispielsweise:Es könnte erwähnenswert sein, dass dies zu
require
einem absoluten Weg führen wird, obwohl ich noch keine Probleme damit habe.quelle
Es gibt eine gute Diskussion zu diesem Thema hier .
Ich hatte das gleiche Architekturproblem: Ich wollte meiner Anwendung mehr Organisation und interne Namespaces geben, ohne:
Am Ende habe ich beschlossen, meinen Code mithilfe von Dateinamenkonventionen anstelle von Verzeichnissen zu organisieren. Eine Struktur würde ungefähr so aussehen:
Dann im Code:
oder nur
und externe Abhängigkeiten sind wie gewohnt von node_modules verfügbar:
Auf diese Weise wird der gesamte Anwendungscode hierarchisch in Modulen organisiert und steht allen anderen Codes relativ zum Anwendungsstamm zur Verfügung.
Der Hauptnachteil ist natürlich, dass Sie in einem Dateibrowser den Baum nicht so erweitern / reduzieren können, als ob er tatsächlich in Verzeichnissen organisiert wäre. Aber ich mag es, dass es sehr explizit ist, woher der gesamte Code kommt, und dass es keine "Magie" verwendet.
quelle
../x/x
was bereits lesbar ist.Angenommen, Ihr Projektstamm ist das aktuelle Arbeitsverzeichnis, sollte dies funktionieren:
quelle
config = require('./config.js');
ist auch gültig.Ich habe viele dieser Lösungen ausprobiert. Am Ende habe ich dies oben in meiner Hauptdatei hinzugefügt (z. B. index.js):
Dadurch wird der Projektstamm zum NODE_PATH hinzugefügt, wenn das Skript geladen wird. Dadurch kann ich jede Datei in meinem Projekt anfordern, indem ich auf ihren relativen Pfad vom Projektstamm verweise, z
var User = require('models/user')
. Diese Lösung sollte funktionieren, solange Sie ein Hauptskript im Projektstamm ausführen, bevor Sie etwas anderes in Ihrem Projekt ausführen.quelle
Einige der Antworten besagen, dass der beste Weg darin besteht, den Code als Paket zum node_module hinzuzufügen. Ich stimme zu und es ist wahrscheinlich der beste Weg, die Anforderungen zu verlieren
../../../
, aber keiner von ihnen gibt tatsächlich einen Weg dazu.Ab Version können
2.0.0
Sie ein Paket aus lokalen Dateien installieren. Dies bedeutet, dass Sie in Ihrem Stammverzeichnis einen Ordner mit allen gewünschten Paketen erstellen können.In package.json können Sie das
modules
(oderfoo
undbar
) als Paket hinzufügen , ohne einen externen Server wie folgt zu veröffentlichen oder zu verwenden:Danach
npm install
können Sie auf den Code zugreifenvar foo = require("foo")
, genau wie bei allen anderen Paketen.Weitere Infos finden Sie hier:
https://docs.npmjs.com/files/package.json#local-paths
und hier, wie man ein Paket erstellt:
https://docs.npmjs.com/getting-started/creating-node-modules
quelle
Sie könnten ein Modul verwenden, das ich erstellt habe, Undot . Es ist nichts Fortgeschrittenes, nur ein Helfer, damit Sie diese Punkthölle mit Einfachheit vermeiden können.
Beispiel:
quelle
Sie könnten so etwas in Ihrer app.js definieren:
und wann immer Sie etwas von der Wurzel benötigen möchten, egal wo Sie sich befinden, verwenden Sie einfach requireFromRoot anstelle der Vanille-Anforderung. Funktioniert bisher ziemlich gut für mich.
quelle
requireFromRoot = ((root) => (resource) => require(`${root}/${resource}`))(__dirname);
. Ich liebe die Lösung, aber müssen Sie wirklich __dirname so binden?require
diese Funktion?Hier ist die tatsächliche Art und Weise, wie ich es seit mehr als 6 Monaten mache. Ich verwende einen Ordner mit dem Namen node_modules als Stammordner im Projekt. Auf diese Weise sucht er immer von überall nach diesem Ordner, den ich als absolut erforderlich bezeichne:
Dies ist nützlicher, wenn Sie in Ordnern verschachtelt sind und das Ändern eines Dateispeicherorts viel weniger Arbeit erfordert, wenn dies absolut festgelegt ist. Ich verwende in meiner gesamten App nur 2 der relativen Anforderungen .
quelle
node_modules
in/src
und lasse/node_modules
für Anbieter Dinge getrennt zu halten. Also habe ich/src/node_modules
für lokalen Code und/node_modules
für Anbieter.NODE_PATH
UmgebungsvariableImho ist der einfachste Weg, dies zu erreichen, indem
node_modules/app
Sie beim Start der App unter (oder wie auch immer Sie es nennen) einen symbolischen Link erstellen, der darauf verweist../app
. Dann können Sie einfach anrufenrequire("app/my/module")
. Symbolische Links sind auf allen wichtigen Plattformen verfügbar.Sie sollten Ihre Daten jedoch weiterhin in kleinere, wartbare Module aufteilen, die über npm installiert werden. Sie können Ihre privaten Module auch über git-url installieren, sodass es keinen Grund gibt, ein monolithisches App-Verzeichnis zu haben.
quelle
In Ihrem eigenen Projekt können Sie jede im Stammverzeichnis verwendete .js-Datei ändern und ihren Pfad zu einer Eigenschaft der
process.env
Variablen hinzufügen . Beispielsweise:Danach können Sie überall auf die Unterkunft zugreifen:
quelle
Eine andere Antwort:
Stellen Sie sich diese Ordnerstruktur vor:
Tests
Dann müssen Sie in test.js Dateien wie diese benötigen:
und in main.js :
Jetzt können Sie damit babel und den babel-plugin-module-resolver verwenden . babelrc- Datei zum Konfigurieren von 2 Stammordnern :
Jetzt können Sie Dateien in Tests und in src auf dieselbe Weise anfordern :
und wenn Sie die Syntax des es6-Moduls verwenden möchten :
dann importieren Sie Dateien in Tests und src wie folgt :
quelle
Ich bin gerade auf diesen Artikel gestoßen, in dem der Pfad des App-Moduls erwähnt wird . Sie können eine Basis wie folgt konfigurieren:
quelle
Konnte das
examples
Verzeichnis nichtnode_modules
ein Symbol mit einem symbolischen Link zum Stammverzeichnis des Projekts enthalten,project -> ../../
sodass die Beispiele verwendet werden könnenrequire('project')
, obwohl dies die Zuordnung nicht entfernt, sondern die Verwendung der Quellerequire('project')
anstelle von ermöglichtrequire('../../')
.Ich habe dies getestet und es funktioniert mit v0.6.18.
Auflistung des
project
Verzeichnisses:Der Inhalt von
index.js
weist einer Eigenschaft desexports
Objekts einen Wert zu und ruftconsole.log
mit einer Nachricht auf, die angibt, dass dies erforderlich war. Der Inhalt vontest.js
istrequire('project')
.quelle
require('project.a')
? Ich denke das könnte bedeutenrequire('project/a')
, obwohlrequire('project').a
es auch möglich ist?node_modules
Verzeichnis im nächstgelegenen übergeordneten Element der Datei befinden, und der Link wäre dann für beide gleich. Siehe nodejs.org/api/…project/node_modules/project -> ../
.Wenn jemand nach einem anderen Weg sucht, um dieses Problem zu umgehen, ist hier mein eigener Beitrag zu den Bemühungen:
Die Grundidee: Sie erstellen eine JSON-Datei im Stammverzeichnis des Projekts, die Ihre Dateipfade Kurznamen zuordnet (oder lassen Sie use-automapper dies für Sie tun). Sie können dann Ihre Dateien / Module unter diesen Namen anfordern. Wie so:
Da ist also das.
quelle
Was ich gerne mache, ist zu nutzen, wie Knoten aus dem Verzeichnis node_module geladen werden.
Wenn man versucht, das Modul "Ding" zu laden, würde man so etwas tun
Der Knoten sucht dann im Verzeichnis 'node_module' nach dem Verzeichnis 'thing'.
Da sich das node_module normalerweise im Stammverzeichnis des Projekts befindet, können wir diese Konsistenz nutzen. (Wenn sich node_module nicht an der Wurzel befindet, müssen Sie mit anderen selbst verursachten Kopfschmerzen umgehen.)
Wenn wir in das Verzeichnis gehen und es dann wieder verlassen, können wir einen konsistenten Pfad zum Stammverzeichnis des Knotenprojekts erhalten.
Wenn wir dann auf das Verzeichnis / happy zugreifen möchten, würden wir dies tun.
Obwohl es ziemlich hackig ist, denke ich, dass es größere Probleme geben wird, wenn sich die Funktionalität des Ladens von node_modules ändert. Dieses Verhalten sollte konsistent bleiben.
Um die Dinge klar zu machen, mache ich das, weil der Name des Moduls keine Rolle spielt.
Ich habe es kürzlich für angle2 verwendet. Ich möchte einen Dienst aus dem Stammverzeichnis laden.
quelle
src/app/my.service
und VSC so konfigurieren, dass nicht relative Importe für Typoskriptdateien verwendet werden.Ich habe dieses kleine Paket geschrieben, mit dem Sie Pakete anhand ihres relativen Pfads vom Projektstamm anfordern können, ohne globale Variablen einzuführen oder Knotenstandards zu überschreiben
https://github.com/Gaafar/pkg-require
Es funktioniert so
quelle
Ich möchte nur die großartige Antwort von Paolo Moretti und Browserify weiterverfolgen. Wenn Sie einen Transpiler (z. B. Babel, Typoskript) verwenden und separate Ordner für Quellcode und transpilierten Code wie
src/
und habendist/
, können Sie eine Variation der Lösungen als verwendenKnotenmodule
Mit folgender Verzeichnisstruktur:
Sie können dann babel etc
src
Verzeichnis zudist
Verzeichnis transpilieren lassen .symlink
Mit symlink können wir einige Verschachtelungsebenen beseitigen:
Eine Einschränkung mit babel --copy-files Die
--copy-files
Flagge vonbabel
geht nicht gut mit Symlinks um. Möglicherweise navigiert es weiter in den..
Symlink und sieht wiederholt endlose Dateien. Eine Problemumgehung besteht darin, die folgende Verzeichnisstruktur zu verwenden:Auf diese Weise wurde der Code unter
src
weiterhinapp
aufgelöstsrc
, während babel keine Symlinks mehr sehen würde.quelle
Ich suchte nach genau der gleichen Einfachheit, um Dateien von jeder Ebene zu benötigen, und fand einen Modul-Alias .
Einfach installieren:
Öffnen Sie Ihre package.json-Datei. Hier können Sie Aliase für Ihre Pfade hinzufügen, z
Und verwenden Sie Ihre Aliase einfach durch:
quelle
Ich habe ein Knotenmodul namens "rekiure" erstellt.
Es ermöglicht Ihnen, ohne die Verwendung von relativen Pfaden zu fordern
es ist super einfach zu bedienen
quelle
Wir sind dabei, einen neuen Weg zu finden, um dieses Problem anzugehen.
Anhand von Beispielen aus anderen bekannten Projekten wie Spring und Guice definieren wir ein "Kontext" -Objekt, das alle "require" -Anweisungen enthält.
Dieses Objekt wird dann zur Verwendung an alle anderen Module übergeben.
Beispielsweise
Dies erfordert, dass wir jedes Modul als eine Funktion schreiben, die Optionen empfängt, was für uns ohnehin eine bewährte Methode ist.
und dann werden Sie sich auf den Kontext beziehen, anstatt Dinge zu benötigen.
var module1Ref = context.moduel1;
Wenn Sie möchten, können Sie einfach eine Schleife schreiben, um die erforderlichen Anweisungen auszuführen
Dies sollte das Leben erleichtern, wenn Sie verspotten möchten (Tests), und Ihr Problem auf dem Weg lösen, während Ihr Code als Paket wiederverwendbar wird.
Sie können den Kontextinitialisierungscode auch wiederverwenden, indem Sie die Beans-Deklaration davon trennen. Zum Beispiel
main.js
könnte Ihre Datei so aussehenDiese Methode gilt auch für externe Bibliotheken. Sie müssen ihre Namen nicht jedes Mal fest codieren, wenn wir sie benötigen. Sie müssen jedoch speziell behandelt werden, da ihre Exporte keine Funktionen sind, die einen Kontext erwarten.
Später können wir Beans auch als Funktionen definieren, die es uns ermöglichen,
require
je nach Umgebung unterschiedliche Module zu verwenden, die jedoch außerhalb des Bereichs dieses Threads liegen.quelle
Ich hatte Probleme mit demselben Problem und schrieb ein Paket namens include .
Fügen Sie Handles ein, die den Stammordner Ihres Projekts ermitteln, indem Sie Ihre Datei package.json suchen, und übergeben Sie dann das von Ihnen angegebene Pfadargument an das native require (), ohne das gesamte relative Pfadproblem. Ich stelle mir dies nicht als Ersatz für require () vor, sondern als Tool für die Verarbeitung nicht gepackter Dateien oder Bibliotheken von Drittanbietern. Etwas wie
Ich hoffe das kann nützlich sein.
quelle
Wenn sich die js-Einstiegspunktdatei Ihrer App (dh die, auf der Sie tatsächlich "node" ausführen) in Ihrem Projektstammverzeichnis befindet, können Sie dies ganz einfach mit dem rootpath npm-Modul tun . Einfach über installieren
... dann ganz oben in der js-Datei des Einstiegspunkts hinzufügen:
Ab diesem Zeitpunkt sind alle erforderlichen Aufrufe nun relativ zum Projektstamm - z. B.
require('../../../config/debugging/log');
wirdrequire('config/debugging/log');
(wo sich der Konfigurationsordner im Projektstamm befindet).quelle
In einfachen Zeilen können Sie Ihren eigenen Ordner als Modul aufrufen:
Dafür benötigen wir: globales und App-Modul-Pfad-Modul
Hier ist "App-Modul-Pfad" das Modul, mit dem Sie dem Suchpfad des Node.js-Moduls zusätzliche Verzeichnisse hinzufügen können. Und "global" ist, dass alles, was Sie an dieses Objekt anhängen, überall in Ihrer App verfügbar ist.
Schauen Sie sich jetzt diesen Ausschnitt an:
__dirname ist das aktuell laufende Verzeichnis des Knotens. Sie können hier Ihren eigenen Pfad angeben, um den Pfad nach dem Modul zu durchsuchen.
quelle