Je voudrais exiger mes fichiers toujours par la racine de mon projet et non par rapport au module actuel.
Par exemple si vous regardez https://github.com/visionmedia/express/blob/2820f2227de0229c5d7f28009aa432f9f3a7b5f9/examples/downloads/app.js ligne 6, vous verrez
express = require('../../')
C’est vraiment mal l’OMI. Imaginez que je voudrais mettre tous mes exemples plus près de la racine que par un seul niveau. Ce serait impossible, car je devrais mettre à jour plus de 30 exemples et plusieurs fois dans chaque exemple. Pour ça:
express = require('../')
Ma solution serait d’avoir un cas particulier pour les racines: si une chaîne commence par $, elle est relative au dossier racine du projet.
Toute aide est la bienvenue, merci
Maintenant, j’utilise require.js, ce qui vous permet d’écrire d’une manière et fonctionne à la fois sur le client et sur le serveur. Require.js vous permet également de créer des chemins personnalisés.
Maintenant, je suis passé à webpack + gulp et j’utilise un traitement avancé pour gérer les modules côté serveur. Voir ici la justification: http://hackhat.com/p/110/module-loader-webpack-vs-requirejs-vs-browserify/
Et à propos de:
var myModule = require.main.require('./path/to/module');
Il nécessite le fichier comme s’il était requirejs par le fichier js principal, donc ça marche plutôt bien tant que votre fichier js principal est à la racine de votre projet … et c’est quelque chose que j’apprécie.
Il y a une section vraiment intéressante dans le manuel de Browserify :
évitant ../../../../../../ ..
Tout dans une application n’appartient pas correctement au npm public et la mise en place d’une mise en pension privée npm ou git rest assez importante dans de nombreux cas. Voici quelques approches pour éviter le problème des chemins
../../../../../../../
.node_modules
Les gens s’objectent parfois à placer des modules spécifiques à une application dans node_modules, car il n’est pas évident de vérifier vos modules internes sans archiver également les modules tiers à partir de npm.
La réponse est assez simple! Si vous avez un fichier
.gitignore
qui ignorenode_modules
:node_modules
Vous pouvez simplement append une exception avec
!
pour chacun de vos modules d’application internes:node_modules/* !node_modules/foo !node_modules/bar
Veuillez noter que vous ne pouvez pas ignorer un sous-répertoire si le parent est déjà ignoré. Ainsi, au lieu d’ignorer
node_modules
, vous devez ignorer tous les répertoires denode_modules
à l’aide de l’node_modules/*
, puis vous pouvez append vos exceptions.Maintenant, n’importe où dans votre application, vous serez en mesure de
require('foo')
ou derequire('bar')
sans avoir un chemin relatif très grand et fragile.Si vous avez beaucoup de modules et souhaitez les séparer des modules tiers installés par npm, vous pouvez simplement les placer tous sous un répertoire dans
node_modules
tel quenode_modules/app
:node_modules/app/foo node_modules/app/bar
Maintenant, vous pourrez
require('app/foo')
ourequire('app/bar')
de n’importe où dans votre application.Dans votre
.gitignore
, ajoutez simplement une exception pournode_modules/app
:node_modules/* !node_modules/app
Si votre application a des configurations configurées dans package.json, vous devez créer un package.json distinct avec son propre champ de transformation dans votre
node_modules/foo
ounode_modules/app/foo
car les transformations ne s’appliquent pas aux limites des modules. Cela rendra vos modules plus robustes face aux changements de configuration dans votre application et il sera plus facile de réutiliser indépendamment les packages en dehors de votre application.lien symbolique
Un autre truc pratique si vous travaillez sur une application où vous pouvez créer des liens symboliques sans avoir à supporter Windows est de créer un lien symbolique entre un dossier
lib/
ouapp/
dansnode_modules
. Depuis la racine du projet, faites:ln -s ../lib node_modules/app
et maintenant, de n’importe où dans votre projet, vous aurez besoin de fichiers dans
lib/
by doingrequire('app/foo.js')
pour obtenirlib/foo.js
chemins personnalisés
Vous verrez peut-être que certains endroits utilisent la variable d’environnement
$NODE_PATH
ouopts.paths
pour append des répertoires pour node et browserify pour rechercher des modules.Contrairement à la plupart des autres plates-formes, l’utilisation d’un tableau de répertoires de chemins de style shell avec
$NODE_PATH
n’est pas aussi favorable dans node que l’utilisation efficace du répertoirenode_modules
.Cela est dû au fait que votre application est plus étroitement couplée à une configuration d’environnement d’exécution, ce qui fait qu’il ya plus de pièces mobiles et que votre application ne fonctionnera que si votre environnement est correctement configuré.
node et browserify tous deux prennent en charge mais découragent l’utilisation de
$NODE_PATH
.
J’aime créer un nouveau dossier node_modules
pour le code partagé, puis laisser le nœud et exiger ce qu’il fait le mieux.
par exemple:
- node_modules // => these are loaded from your package.json - app - node_modules // => add node-style modules - helper.js - models - user - car - package.json - .gitignore
Par exemple, si vous êtes dans car/index.js
vous pouvez require('helper')
et node le trouvera!
node possède un algorithme astucieux pour résoudre les modules qui est unique parmi les plates-formes rivales.
Si vous avez require('./foo.js')
de /beep/boop/bar.js
, le noeud recherchera ./foo.js
dans /beep/boop/foo.js
. Les chemins qui commencent par ./
ou ../
sont toujours locaux au fichier qui appelle require()
.
Si toutefois vous avez besoin d’un nom non relatif tel que require('xyz')
de /beep/boop/foo.js
, le noeud recherche ces chemins dans l’ordre, en s’arrêtant à la première correspondance et en générant une erreur si rien n’est trouvé:
/beep/boop/node_modules/xyz /beep/node_modules/xyz /node_modules/xyz
Pour chaque répertoire xyz
existant, node recherchera d’abord un xyz/package.json
pour voir si un champ "main"
existe. Le champ "main"
définit quel fichier doit être pris en charge si vous avez require()
du chemin du répertoire.
Par exemple, si /beep/node_modules/xyz
est la première correspondance et /beep/node_modules/xyz/package.json
a:
{ "name": "xyz", "version": "1.2.3", "main": "lib/abc.js" }
les exportations de /beep/node_modules/xyz/lib/abc.js
seront alors renvoyées par require('xyz')
.
S’il n’y a pas de package.json
ou de champ "main"
, index.js
est supposé:
/beep/node_modules/xyz/index.js
Cela semble “vraiment mauvais” mais donnez-lui du temps. En fait, c’est vraiment bien. Les require()
s explicites donnent une transparence totale et une facilité de compréhension qui est comme une bouffée d’air frais pendant le cycle de vie d’un projet.
Pensez-y de cette façon: vous lisez un exemple en plongeant vos orteils dans Node.js et vous avez décidé que c’était «vraiment désagréable». Vous êtes des leaders incontournables de la communauté Node.js, des personnes qui ont enregistré plus d’heures d’écriture et de maintenance des applications Node.js que quiconque. Quelle est la chance que l’auteur ait commis une telle erreur de recrue? (Et je suis d’accord, d’après mon arrière-plan Ruby et Python, il semble au début comme un désastre.)
Il y a beaucoup de battage médiatique et de contre-battage autour de Node.js. Mais lorsque la poussière retombera, nous admettrons que les modules explicites et les packages «locaux d’abord» ont été un moteur majeur de l’adoption.
Bien sûr, node_modules
du répertoire en cours, puis le parent, puis grand-parent, arrière-grand-parent, etc. est recherché. Donc, les paquets que vous avez installés fonctionnent déjà de cette façon. Habituellement, vous pouvez require("express")
de n’importe où dans votre projet et cela fonctionne très bien.
Si vous vous retrouvez en train de charger des fichiers communs depuis la racine de votre projet (peut-être parce que ce sont des fonctions utilitaires communes), cela indique que le moment est venu de créer un paquet. Les paquets sont très simples: déplacez vos fichiers dans node_modules/
et placez-y un package.json
. Voila! Tout dans cet espace de noms est accessible depuis l’ensemble de votre projet. Les packages sont la manière correcte d’obtenir votre code dans un espace de noms global.
Personnellement, je n’utilise pas ces techniques, mais elles répondent à votre question et, bien sûr, vous connaissez votre propre situation mieux que moi.
Vous pouvez définir $NODE_PATH
à la racine de votre projet. Ce répertoire sera recherché lorsque vous en aurez require()
.
Ensuite, vous pourriez compromettre et exiger un fichier local commun de tous vos exemples. Ce fichier commun réexporte simplement le fichier true dans le répertoire grand-parent.
examples / downloads / app.js (et bien d’autres encore)
var express = require('./express')
examples / downloads / express.js
module.exports = require('../../')
Maintenant, lorsque vous déplacez ces fichiers, le pire des cas est la réparation du module de cale .
Regardez node-rfr .
C’est aussi simple que cela:
var rfr = require('rfr'); var myModule = rfr('projectSubDir/myModule');
À mon humble avis, le plus simple est de définir votre propre fonction dans le cadre d’un object GLOBAL
. Créez projRequire.js
dans la racine de votre projet avec le contenu suivant:
var projectDir = __dirname; module.exports = GLOBAL.projRequire = function(module) { return require(projectDir + module); }
Dans votre fichier principal avant d’avoir require
de modules spécifiques au projet:
// init projRequire require('./projRequire');
Après ça, ça marche pour moi:
// main file projRequire('/lib/lol'); // index.js at projectDir/lib/lol/index.js console.log('Ok');
@Totty, je suis venu avec une autre solution, qui pourrait fonctionner pour le cas que vous avez décrit dans les commentaires. Description va être tl;dr
, donc je ferais mieux de montrer une image avec la structure de mon projet de test .
J’utilise process.cwd()
dans mes projets. Par exemple:
var Foo = require(process.cwd() + '/common/foo.js');
Il peut être intéressant de noter que cela se traduira par un chemin absolu, même si je n’ai pas encore rencontré de problèmes avec cela.
Il y a une bonne discussion de ce problème ici .
J’ai rencontré le même problème architectural: vouloir un moyen de donner à mon application plus d’organisation et d’espaces de noms internes, sans:
Finalement, j’ai décidé d’organiser mon code en utilisant des conventions de nommage de fichiers plutôt que des répertoires. Une structure ressemblerait à quelque chose comme:
Puis dans le code:
var app_config = require('./app.config'); var app_models_foo = require('./app.models.foo');
ou juste
var config = require('./app.config'); var foo = require('./app.models.foo');
et les dépendances externes sont disponibles depuis node_modules comme d’habitude:
var express = require('express');
De cette manière, tout code d’application est hiérarchiquement organisé en modules et disponible pour tous les autres codes relatifs à la racine de l’application.
Le principal inconvénient est bien sûr que dans un navigateur de fichiers, vous ne pouvez pas développer / réduire l’arborescence comme si elle était réellement organisée en répertoires. Mais j’aime le fait qu’il soit très explicite quant à l’origine de tout le code et qu’il n’utilise aucune «magie».
En supposant que votre racine de projet est le répertoire de travail en cours, cela devrait fonctionner:
// require built-in path module path = require('path'); // require file relative to current working directory config = require( path.resolve('.','config.js') );
Voici ce que je fais depuis plus de 6 mois. J’utilise un dossier nommé node_modules en tant que dossier racine dans le projet, de cette manière, il recherchera toujours ce dossier partout où j’appelle un besoin absolu:
Ceci est plus utile lorsque vous êtes nested dans des dossiers et qu’il est beaucoup moins difficile de modifier l’emplacement d’un fichier s’il est défini de manière absolue. Je n’utilise que 2 les besoins relatifs dans toute mon application .
Vous pouvez définir quelque chose comme ceci dans votre app.js:
requireFromRoot = (function(root) { return function(resource) { return require(root+"/"+resource); } })(__dirname);
Et puis, chaque fois que vous voulez demander quelque chose à la racine, peu importe où vous êtes, utilisez simplement requireFromRoot au lieu de vanilla. Fonctionne plutôt bien pour moi jusqu’à présent.
J’ai essayé plusieurs de ces solutions. J’ai fini par append ceci en haut de mon fichier principal (par exemple, index.js):
process.env.NODE_PATH = __dirname; require('module').Module._initPaths();
Cela ajoute la racine du projet à NODE_PATH lorsque le script est chargé. Cela me permet d’exiger n’importe quel fichier de mon projet en référençant son chemin relatif depuis la racine du projet, tel que var User = require('models/user')
. Cette solution devrait fonctionner tant que vous exécutez un script principal dans la racine du projet avant d’exécuter tout autre élément de votre projet.
À mon avis, le moyen le plus simple d’y parvenir est de créer un lien symbolique au démarrage de l’application sur node_modules/app
(ou peu importe node_modules/app
vous l’appelez) qui pointe vers ../app
. Ensuite, vous pouvez simplement appeler require("app/my/module")
. Des liens symboliques sont disponibles sur toutes les principales plates-formes.
Cependant, vous devez toujours diviser vos fichiers en modules plus petits et maintenables, installés via npm. Vous pouvez également installer vos modules privés via git-url, il n’y a donc aucune raison d’avoir un répertoire d’application monolithique.
Dans votre propre projet, vous pouvez modifier tout fichier .js utilisé dans le répertoire racine et append son chemin à une propriété de la variable process.env
. Par exemple:
// in index.js process.env.root = __dirname;
Ensuite, vous pouvez accéder à la propriété partout:
// in app.js express = require(process.env.root);
Vous pourriez utiliser un module que j’ai créé, Undot . Il n’y a rien de plus avancé, juste un assistant pour éviter ces points de folie avec simplicité.
Exemple:
var undot = require('undot'); var User = undot('models/user'); var config = undot('config'); var test = undot('test/api/user/auth');
Ce que j’aime faire, c’est exploiter comment le nœud se charge depuis le répertoire node_module pour cela.
Si on essaie de charger le module “thing”, on ferait quelque chose comme
require('thing');
Node recherchera alors le répertoire ‘thing’ dans le répertoire ‘node_module’.
Puisque node_module est normalement à la racine du projet, nous pouvons tirer parti de cette cohérence. (Si node_module n’est pas à la racine, alors vous avez d’autres maux de tête auto-induits à traiter.)
Si nous allons dans le répertoire et que nous en sortons, nous pouvons obtenir un chemin cohérent vers la racine du projet de noeud.
require('thing/../../');
Ensuite, si nous voulons accéder au répertoire / happy, nous le ferons.
require('thing/../../happy');
Bien que ce soit un peu pirate, je pense que si la fonctionnalité de chargement de node_modules change, il y aura de plus gros problèmes à résoudre. Ce comportement doit restr cohérent.
Pour clarifier les choses, je le fais car le nom du module n’a pas d’importance.
require('root/../../happy');
Je l’ai utilisé récemment pour angular2. Je veux charger un service depuis la racine.
import {MyService} from 'root/../../app/services/http/my.service';
Certaines des réponses indiquent que le meilleur moyen est d’append le code à node_module en tant que paquet, je suis d’accord et c’est probablement le meilleur moyen de perdre le ../../../
in requirejs mais aucun ne donne réellement un moyen de le faire.
à partir de la version 2.0.0
vous pouvez installer un paquet à partir de fichiers locaux, ce qui signifie que vous pouvez créer un dossier dans votre racine avec tous les paquets que vous voulez,
-modules --foo --bar -app.js -package.json
Ainsi, dans package.json, vous pouvez append les modules
(ou foo
et bar
) en tant que paquet sans publier ou utiliser un serveur externe comme celui-ci:
{ "name": "baz", "dependencies": { "bar": "file: ./modules/bar", "foo": "file: ./modules/foo" } }
Après cela, vous npm install
, et vous pouvez accéder au code avec var foo = require("foo")
, comme vous le faites avec tous les autres paquets.
Plus d’informations peuvent être trouvées ici:
https://docs.npmjs.com/files/package.json#local-paths
et voici comment créer un package:
https://docs.npmjs.com/getting-started/creating-node-modules
Le répertoire des examples
ne pourrait-il pas contenir un node_modules
avec un lien symbolique vers la racine du projet project -> ../../
permettant ainsi aux exemples d’utiliser require('project')
, bien que cela ne supprime pas le mapping, cela permet à la source d’utiliser un require('project')
plutôt que d’ require('../../')
.
Je l’ai testé et il fonctionne avec la v0.6.18.
Liste du répertoire du 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 -> ../../
Le contenu de index.js
atsortingbue une valeur à une propriété de l’object exports
et appelle console.log
avec un message indiquant qu’il était requirejs. Le contenu de test.js
est test.js
require('project')
.
Si quelqu’un cherche encore une autre façon de contourner ce problème, voici ma propre consortingbution à cet effort:
L’idée de base: vous créez un fichier JSON à la racine du projet qui mappe vos chemins de fichiers à des noms abrégés (ou à use-automapper le fait pour vous). Vous pouvez ensuite demander vos fichiers / modules en utilisant ces noms. Ainsi:
var use = require('use-import'); var MyClass = use('MyClass');
Donc, il y a ça.
J’ai écrit ce petit paquet qui vous permet d’exiger des paquets par leur chemin relatif depuis la racine du projet, sans introduire de variables globales ni remplacer les valeurs par défaut des nœuds.
https://github.com/Gaafar/pkg-require
Ça marche comme ça
// 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()
Une autre réponse:
Imaginez cette structure de dossiers:
des tests
Ensuite, dans test.js , vous devez exiger des fichiers comme ceci:
const foo = require("../src/subdir/foo"); const bar = require("../src/subdir/bar"); const main = require("../src/main"); const _ = require("lodash");
et dans main.js :
const foo = require("./subdir/foo"); const bar = require("./subdir/bar"); const _ = require("lodash");
Maintenant, vous pouvez utiliser babel et le babel-plugin-module-resolver avec ceci. Fichier babelrc pour configurer 2 dossiers racine:
{ "plugins": [ ["module-resolver", { "root": ["./src", "./src/subdir"] }] ] }
Maintenant, vous pouvez exiger des fichiers de la même manière dans les tests et dans src :
const foo = require("foo"); const bar = require("bar"); const main = require("main"); const _ = require("lodash");
et si vous voulez utiliser la syntaxe du module es6 :
{ "plugins": [ ["module-resolver", { "root": ["./src", "./src/subdir"] }], "transform-es2015-modules-commonjs" ] }
puis vous importez des fichiers dans des tests et src comme ceci:
import foo from "foo" import bar from "bar" import _ from "lodash"
J’ai créé un module de noeud appelé “rekiure”
il vous permet d’exiger sans utiliser de chemins relatifs
c’est super facile à utiliser
Nous sums sur le point d’essayer une nouvelle façon de résoudre ce problème.
En prenant des exemples d’autres projets connus tels que le spring et la guice, nous définirons un object “context” qui contiendra toutes les instructions “require”.
Cet object sera ensuite transmis à tous les autres modules pour être utilisé.
Par exemple
var context = {} context.module1 = require("./module1")( { "context" : context } ) context.module2 = require("./module2")( { "context" : context } )
Cela nous oblige à écrire chaque module en tant que fonction recevant des choix, ce qui nous semble être la meilleure pratique de toute façon.
module.exports = function(context){ ... }
et ensuite vous vous référez au contexte au lieu de demander des choses.
var module1Ref = context.moduel1;
Si vous le souhaitez, vous pouvez facilement écrire une boucle pour effectuer les instructions requirejses
var context = {}; var beans = {"module1" : "./module1","module2" : "./module2" }; for ( var i in beans ){ if ( beans.hasOwnProperty(i)){ context[i] = require(beans[i])(context); } };
Cela devrait vous simplifier la vie (tests) et résoudre votre problème tout en rendant votre code réutilisable en tant que package.
Vous pouvez également réutiliser le code d’initialisation du contexte en séparant la déclaration des beans. Par exemple, votre fichier main.js
pourrait ressembler à ça
var beans = { ... }; // like before var context = require("context")(beans); // this example assumes context is a node_module since it is reused..
Cette méthode s’applique également aux bibliothèques externes, pas besoin de coder en dur leurs noms à chaque fois que nous en avons besoin – cependant, cela nécessitera un traitement spécial car leurs exportations ne sont pas des fonctions qui attendent un contexte.
Plus tard, nous pouvons également définir les beans comme des fonctions – ce qui nous permettra d’ require
différents modules en fonction de l’environnement – mais cela n’est pas à la scope de ce thread.
J’avais des problèmes avec ce même problème, alors j’ai écrit un paquet appelé include .
Incluez des poignées indiquant le dossier racine de votre projet en localisant votre fichier package.json, puis transmettez l’argument de chemin que vous lui avez donné au require () natif sans tout le chemin d’access relatif. I imagine this not as a replacement for require(), but a tool for requiring handling non-packaged / non-third-party files or libraries. Quelque chose comme
var async = require('async'), foo = include('lib/path/to/foo')
I hope this can be useful.
If your app’s entry point js file (ie the one you actually run “node” on) is in your project root directory, you can do this really easily with the rootpath npm module . Simply install it via
npm install --save rootpath
…then at the very top of the entry point js file, add:
require('rootpath')();
From that point forward all require calls are now relative to project root – eg require('../../../config/debugging/log');
becomes require('config/debugging/log');
(where the config folder is in the project root).
In simple lines, u can call your own folder as module :
For that we need: global and app-module-path module
here “App-module-path” is the module ,it enables you to add additional directories to the Node.js module search path And “global” is, anything that you attach to this object will b available everywhere in your app.
Now take a look at this snippet:
global.appBasePath = __dirname; require('app-module-path').addPath(appBasePath);
__dirname is current running directory of node.You can give your own path here to search the path for module.
Just want to follow up on the great answer from Paolo Moretti and Browserify. If you are using a transstackr (eg, babel, typescript) and you have separate folders for source and transstackd code like src/
and dist/
, you could use a variation of the solutions as
With the following directory structure:
app node_modules ... // normal npm dependencies for app src node_modules app ... // source code dist node_modules app ... // transstackd code
you can then let babel etc to transstack src
directory to dist
directory.
Using symlink we can get rid some levels of nesting:
app node_modules ... // normal npm dependencies for app src node_modules app // symlinks to '..' ... // source code dist node_modules app // symlinks to '..' ... // transstackd code
A caveat with babel –copy-files The --copy-files
flag of babel
does not deal with symlinks well. It may keep navigating into the ..
symlink and recusively seeing endless files. A workaround is to use the following directory structure:
app node_modules app // symlink to '../src' ... // normal npm dependencies for app src ... // source code dist node_modules app // symlinks to '..' ... // transstackd code
In this way, code under src
will still have app
resolved to src
, whereas babel would not see symlinks anymore.
Just came across this article which mentions app-module-path . It allows you to configure a base like this:
require('app-module-path').addPath(baseDir);
Some time ago I created module for loading modules relative to pre-defined paths.
You can use it instead of require.
irequire.prefix('controllers',join.path(__dirname,'app/master')); var adminUsersCtrl = irequire("controllers:admin/users"); var net = irequire('net');
Maybe it will be usefull for someone..
Whilst these answers work they do not address the problem with npm test
If, for example, I create a global variable in server.js, it will not be set for my test suite execution.
To set a global appRoot variable that will avoid the ../../../ problem and will be available in both npm start AND npm test see:
Mocha tests with extra options or parameters
Note that this is the new official mocha solution .