node.js nécessite tous les fichiers dans un dossier?

Réponses:

516

Lorsque require reçoit le chemin d'un dossier, il recherche un fichier index.js dans ce dossier; s'il y en a un, il l'utilise, et s'il n'y en a pas, il échoue.

Il serait probablement plus judicieux (si vous avez le contrôle sur le dossier) de créer un fichier index.js, puis d'affecter tous les "modules" et de simplement l'exiger.

yourfile.js

var routes = require("./routes");

index.js

exports.something = require("./routes/something.js");
exports.others = require("./routes/others.js");

Si vous ne connaissez pas les noms de fichiers, vous devez écrire une sorte de chargeur.

Exemple de travail d'un chargeur:

var normalizedPath = require("path").join(__dirname, "routes");

require("fs").readdirSync(normalizedPath).forEach(function(file) {
  require("./routes/" + file);
});

// Continue application logic here
tbranyen
la source
152
Pour ajouter quelques éclaircissements: Quand requireest donné le chemin d'un dossier, il recherchera un index.jsdans ce dossier; s'il y en a un, il l'utilise, et s'il n'y en a pas, il échoue. Voir github.com/christkv/node-mongodb-native pour un exemple concret de ceci: Il y a index.jsdans le répertoire racine qui nécessite ./lib/mongodb, un répertoire; ./lib/mongodb/index.js'rend tout le reste de ce répertoire disponible.
Trevor Burnham
22
requireest une fonction synchrone, il n'y a donc aucun avantage à être rappelé. J'utiliserais plutôt fs.readdirSync.
Rafał Sobota
4
Merci, j'ai rencontré ce même problème aujourd'hui et j'ai pensé "pourquoi n'y a-t-il pas de besoin ('./ routes / *')?".
Richard Clayton
3
@RobertMartin, c'est utile lorsque vous n'avez pas besoin d'une poignée pour tout ce qui est exporté; par exemple, si je voulais simplement passer une instance d'application Express à un ensemble de fichiers qui lieraient des routes.
Richard Clayton
2
@TrevorBurnham Pour ajouter, le fichier principal (ie index.js) d'un répertoire peut être modifié via package.jsondans ce répertoire. Comme ça:{main: './lib/my-custom-main-file.js'}
antitoxique
187

Je recommande d'utiliser glob pour accomplir cette tâche.

var glob = require( 'glob' )
  , path = require( 'path' );

glob.sync( './routes/**/*.js' ).forEach( function( file ) {
  require( path.resolve( file ) );
});
Diogo Cardoso
la source
12
Tout le monde devrait utiliser cette réponse;)
Jamie Hutber
2
Meilleure réponse! Plus facile que toutes les autres options, en particulier pour les dossiers enfants récursifs contenant des fichiers que vous devez inclure.
ngDeveloper
1
Recommandez la globalisation en raison du contrôle global que vous avez sur les ensembles de critères de spécification de fichier que vous pouvez spécifier.
stephenwil
6
glob? tu veux dire glob-savior-of-the-nodejs-race. Meilleure réponse.
deepelement
3
Utilisez map () pour enregistrer les liens: const routes = glob.sync ('./ routes / ** / *. Js'). Map (file => require (path.resolve (file)));
lexa-b
71

Sur la base de la solution de @ tbranyen, je crée un index.jsfichier qui charge des javascripts arbitraires dans le dossier actuel dans le cadre du exports.

// Load `*.js` under current directory as properties
//  i.e., `User.js` will become `exports['User']` or `exports.User`
require('fs').readdirSync(__dirname + '/').forEach(function(file) {
  if (file.match(/\.js$/) !== null && file !== 'index.js') {
    var name = file.replace('.js', '');
    exports[name] = require('./' + file);
  }
});

Ensuite, vous pouvez requirece répertoire à partir de n'importe où ailleurs.

Greg Wang
la source
5
Je sais que cela a plus d'un an, mais vous pouvez également avoir besoin de fichiers JSON, alors peut-être que quelque chose comme ça /\.js(on)?$/serait mieux. Ce n'est pas non plus !== nullredondant?
59

Une autre option consiste à utiliser le package require-dir qui vous permet d'effectuer les opérations suivantes. Il prend également en charge la récursivité.

var requireDir = require('require-dir');
var dir = requireDir('./path/to/dir');
studgeek
la source
3
+1 pour require-dircar il exclut automatiquement le fichier appelant (index) et revient par défaut au répertoire courant. Parfait.
biofractal
2
Dans npm, il existe quelques autres packages similaires: require-all, require-directory, require-dir et autres. La version la plus téléchargée semble avoir besoin de tout, au moins en juillet 2015.
Mnebuerquo
require-dir est désormais le plus téléchargé (mais il ne prend notamment pas en charge l'exclusion de fichiers au moment de la rédaction)
Sean Anderson
Trois ans après le commentaire de Sean ci-dessus, a require-dirajouté une filteroption.
givemesnacks
7

J'ai un dossier / champs plein de fichiers avec une seule classe chacun, ex:

fields/Text.js -> Test class
fields/Checkbox.js -> Checkbox class

Déposez ceci dans fields / index.js pour exporter chaque classe:

var collectExports, fs, path,
  __hasProp = {}.hasOwnProperty;

fs = require('fs');    
path = require('path');

collectExports = function(file) {
  var func, include, _results;

  if (path.extname(file) === '.js' && file !== 'index.js') {
    include = require('./' + file);
    _results = [];
    for (func in include) {
      if (!__hasProp.call(include, func)) continue;
      _results.push(exports[func] = include[func]);
    }
    return _results;
  }
};

fs.readdirSync('./fields/').forEach(collectExports);

Cela fait que les modules agissent plus comme ils le feraient en Python:

var text = new Fields.Text()
var checkbox = new Fields.Checkbox()
mélangé
la source
6

Une autre option consiste à exiger-dir-all combinant les fonctionnalités des packages les plus populaires.

Le plus populaire require-dirn'a pas d'options pour filtrer les fichiers / répertoires et n'a pas de mapfonction (voir ci-dessous), mais utilise une petite astuce pour trouver le chemin actuel du module.

Le second par la popularité require-allest le filtrage et le prétraitement des expressions rationnelles, mais il manque un chemin relatif, vous devez donc utiliser __dirname(cela a des avantages et des contras) comme:

var libs = require('require-all')(__dirname + '/lib');

Mentionné ici require-indexest assez minimaliste.

Avec mapvous, vous pouvez effectuer un prétraitement, comme créer des objets et transmettre des valeurs de configuration (en supposant que les modules sous les constructeurs exportent):

// Store config for each module in config object properties 
// with property names corresponding to module names 
var config = {
  module1: { value: 'config1' },
  module2: { value: 'config2' }
};

// Require all files in modules subdirectory 
var modules = require('require-dir-all')(
  'modules', // Directory to require 
  { // Options 
    // function to be post-processed over exported object for each require'd module 
    map: function(reqModule) {
      // create new object with corresponding config passed to constructor 
      reqModule.exports = new reqModule.exports( config[reqModule.name] );
    }
  }
);

// Now `modules` object holds not exported constructors, 
// but objects constructed using values provided in `config`.
alykoshin
la source
5

Je sais que cette question a plus de 5 ans, et les réponses données sont bonnes, mais je voulais quelque chose d'un peu plus puissant pour express, alors j'ai créé le express-map2package pour npm. J'allais simplement le nommer express-map, mais les gens de Yahoo ont déjà un paquet avec ce nom, j'ai donc dû renommer mon paquet.

1. utilisation de base:

app.js (or whatever you call it)

var app = require('express'); // 1. include express

app.set('controllers',__dirname+'/controllers/');// 2. set path to your controllers.

require('express-map2')(app); // 3. patch map() into express

app.map({
    'GET /':'test',
    'GET /foo':'middleware.foo,test',
    'GET /bar':'middleware.bar,test'// seperate your handlers with a comma. 
});

utilisation du contrôleur:

//single function
module.exports = function(req,res){

};

//export an object with multiple functions.
module.exports = {

    foo: function(req,res){

    },

    bar: function(req,res){

    }

};

2. utilisation avancée, avec préfixes:

app.map('/api/v1/books',{
    'GET /': 'books.list', // GET /api/v1/books
    'GET /:id': 'books.loadOne', // GET /api/v1/books/5
    'DELETE /:id': 'books.delete', // DELETE /api/v1/books/5
    'PUT /:id': 'books.update', // PUT /api/v1/books/5
    'POST /': 'books.create' // POST /api/v1/books
});

Comme vous pouvez le voir, cela permet d'économiser une tonne de temps et de simplifier l'écriture, la maintenance et la compréhension du routage de votre application. il prend en charge tous les verbes http qui expriment les supports, ainsi que la .all()méthode spéciale .

r3wt
la source
3

Un module que j'ai utilisé pour ce cas d'utilisation exact est require-all .

Il nécessite récursivement tous les fichiers dans un répertoire donné et ses sous-répertoires tant qu'ils ne correspondent pas à la excludeDirspropriété.

Il permet également de spécifier un filtre de fichiers et comment dériver les clés du hachage retourné à partir des noms de fichiers.

Thorsten Lorenz
la source
2

J'utilise un module de copie de modules de nœuds pour créer un fichier unique nécessitant tous les fichiers de notre système basé sur NodeJS.

Le code de notre fichier utilitaire ressemble à ceci:

/**
 * Module dependencies.
 */

var copy = require('copy-to');
copy(require('./module1'))
.and(require('./module2'))
.and(require('./module3'))
.to(module.exports);

Dans tous les fichiers, la plupart des fonctions sont écrites comme des exportations, comme ceci:

exports.function1 = function () { // function contents };
exports.function2 = function () { // function contents };
exports.function3 = function () { // function contents };

Donc, pour utiliser n'importe quelle fonction d'un fichier, il suffit d'appeler:

var utility = require('./utility');

var response = utility.function2(); // or whatever the name of the function is
scottnath
la source
2

Développer cette glob solution. Faites-le si vous souhaitez importer tous les modules d'un répertoire dans index.js, puis l'importer index.jsdans une autre partie de l'application. Notez que les littéraux de modèle ne sont pas pris en charge par le moteur de mise en évidence utilisé par stackoverflow, le code peut donc sembler étrange ici.

const glob = require("glob");

let allOfThem = {};
glob.sync(`${__dirname}/*.js`).forEach((file) => {
  /* see note about this in example below */
  allOfThem = { ...allOfThem, ...require(file) };
});
module.exports = allOfThem;

Exemple complet

Structure du répertoire

globExample/example.js
globExample/foobars/index.js
globExample/foobars/unexpected.js
globExample/foobars/barit.js
globExample/foobars/fooit.js

globExample / example.js

const { foo, bar, keepit } = require('./foobars/index');
const longStyle = require('./foobars/index');

console.log(foo()); // foo ran
console.log(bar()); // bar ran
console.log(keepit()); // keepit ran unexpected

console.log(longStyle.foo()); // foo ran
console.log(longStyle.bar()); // bar ran
console.log(longStyle.keepit()); // keepit ran unexpected

globExample / foobars / index.js

const glob = require("glob");
/*
Note the following style also works with multiple exports per file (barit.js example)
but will overwrite if you have 2 exports with the same
name (unexpected.js and barit.js have a keepit function) in the files being imported. As a result, this method is best used when
your exporting one module per file and use the filename to easily identify what is in it.

Also Note: This ignores itself (index.js) by default to prevent infinite loop.
*/

let allOfThem = {};
glob.sync(`${__dirname}/*.js`).forEach((file) => {
  allOfThem = { ...allOfThem, ...require(file) };
});

module.exports = allOfThem;

globExample / foobars / inattendu.js

exports.keepit = () => 'keepit ran unexpected';

globExample / foobars / barit.js

exports.bar = () => 'bar run';

exports.keepit = () => 'keepit ran';

globExample / foobars / fooit.js

exports.foo = () => 'foo ran';

Du projet à l'intérieur avec glob installé , exécuteznode example.js

$ node example.js
foo ran
bar run
keepit ran unexpected
foo ran
bar run
keepit ran unexpected
jtlindsey
la source
1

Exiger tous les fichiers du routesdossier et appliquer en tant que middleware. Aucun module externe requis.

// require
const path = require("path");
const { readdirSync } = require("fs");

// apply as middleware
readdirSync("./routes").map((r) => app.use("/api", require("./routes/" + r)));
Ryan Dhungel
la source
0

En utilisant cette fonction, vous pouvez exiger un répertoire entier.

const GetAllModules = ( dirname ) => {
    if ( dirname ) {
        let dirItems = require( "fs" ).readdirSync( dirname );
        return dirItems.reduce( ( acc, value, index ) => {
            if ( PATH.extname( value ) == ".js" && value.toLowerCase() != "index.js" ) {
                let moduleName = value.replace( /.js/g, '' );
                acc[ moduleName ] = require( `${dirname}/${moduleName}` );
            }
            return acc;
        }, {} );
    }
}

// calling this function.

let dirModules = GetAllModules(__dirname);
M. Hamza Rajput
la source
-2

Si vous incluez tous les fichiers de * .js dans l'exemple de répertoire ("app / lib / *. Js"):

Dans le répertoire app / lib

example.js:

module.exports = function (example) { }

exemple-2.js:

module.exports = function (example2) { }

Dans l'application d'annuaire, créez index.js

index.js:

module.exports = require('./app/lib');
Faizal Pribadi
la source