node.js benötigen alle Dateien in einem Ordner?

Antworten:

515

Wenn require den Pfad eines Ordners erhält, sucht er in diesem Ordner nach einer index.js-Datei. Wenn es eine gibt, wird diese verwendet, und wenn dies nicht der Fall ist, schlägt sie fehl.

Es wäre wahrscheinlich am sinnvollsten (wenn Sie die Kontrolle über den Ordner haben), eine index.js-Datei zu erstellen und dann alle "Module" zuzuweisen und diese dann einfach zu benötigen.

yourfile.js

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

index.js

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

Wenn Sie die Dateinamen nicht kennen, sollten Sie eine Art Loader schreiben.

Arbeitsbeispiel eines Laders:

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

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

// Continue application logic here
tbranyen
quelle
152
Um einige Erläuterungen hinzuzufügen: Wenn requireder Pfad eines Ordners angegeben wird, wird index.jsin diesem Ordner nach einem gesucht. Wenn es eine gibt, wird diese verwendet, und wenn dies nicht der Fall ist, schlägt sie fehl. Ein Beispiel aus der Praxis finden Sie unter github.com/christkv/node-mongodb-native : index.jsIm Stammverzeichnis ist ein Verzeichnis erforderlich ./lib/mongodb, für das ein Verzeichnis erforderlich ist. ./lib/mongodb/index.js'stellt alles andere in diesem Verzeichnis zur Verfügung.
Trevor Burnham
22
requireist eine synchrone Funktion, sodass der Rückruf keine Vorteile bietet. Ich würde stattdessen fs.readdirSync verwenden.
Rafał Sobota
4
Vielen Dank, bin heute auf dasselbe Problem gestoßen und dachte: "Warum gibt es keine Anforderung ('./ Routen / *')?".
Richard Clayton
3
@RobertMartin ist nützlich, wenn Sie für nichts Exportiertes ein Handle benötigen. Zum Beispiel, wenn ich nur eine Express-App-Instanz an eine Reihe von Dateien übergeben wollte, die Routen binden würden.
Richard Clayton
2
@TrevorBurnham Zum Hinzufügen kann die Hauptdatei (dh index.js) eines Verzeichnisses über package.jsonin diesem Verzeichnis geändert werden . Wie so:{main: './lib/my-custom-main-file.js'}
Antitoxikum
187

Ich empfehle, glob zu verwenden, um diese Aufgabe zu erfüllen.

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

glob.sync( './routes/**/*.js' ).forEach( function( file ) {
  require( path.resolve( file ) );
});
Diogo Cardoso
quelle
12
Jeder sollte diese Antwort verwenden;)
Jamie Hutber
2
Beste Antwort! Einfacher als alle anderen Optionen, insbesondere für rekursive untergeordnete Ordner mit Dateien, die Sie einschließen müssen.
ngDeveloper
1
Empfehlen Sie Globbing aufgrund der allgemeinen Kontrolle über die Dateispezifikationskriterien, die Sie angeben können.
stephenwil
6
glob? du meinst glob-savior-of-the-nodejs-race. Beste Antwort.
deepelement
3
Verwenden Sie map () zum Speichern von Links: const route = glob.sync ('./ routen / ** / *. Js'). Map (file => require (path.resolve (file)));
Lexa-B
71

Basierend auf der Lösung von @ tbranyen erstelle ich eine index.jsDatei, die beliebige Javascripts unter den aktuellen Ordner als Teil des lädt 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);
  }
});

Dann können Sie requiredieses Verzeichnis von jedem anderen Ort aus.

Greg Wang
quelle
5
Ich weiß, dass dies mehr als ein Jahr alt ist, aber Sie können auch JSON-Dateien benötigen, also wäre vielleicht so etwas /\.js(on)?$/besser. Auch ist nicht !== nullredundant?
59

Eine andere Option ist die Verwendung des Pakets require-dir , mit dem Sie Folgendes tun können. Es unterstützt auch die Rekursion.

var requireDir = require('require-dir');
var dir = requireDir('./path/to/dir');
studgeek
quelle
3
+1 für, require-dirweil die aufrufende Datei (Index) automatisch ausgeschlossen wird und standardmäßig das aktuelle Verzeichnis verwendet wird. Perfekt.
Biofractal
2
In npm gibt es einige weitere ähnliche Pakete: require-all, require-directory, require-dir und andere. Die am meisten heruntergeladenen scheinen mindestens im Juli 2015 erforderlich zu sein.
Mnebuerquo
require-dir ist jetzt das am meisten heruntergeladene (aber insbesondere unterstützt es den Ausschluss von Dateien zum Zeitpunkt des Schreibens nicht)
Sean Anderson
Drei Jahre nach Seans Kommentar oben wurde require-direine filterOption hinzugefügt .
Givemesnacks
7

Ich habe einen Ordner / Felder voller Dateien mit jeweils einer Klasse, z.

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

Legen Sie dies in fields / index.js ab, um jede Klasse zu exportieren:

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

Dadurch verhalten sich die Module mehr wie in Python:

var text = new Fields.Text()
var checkbox = new Fields.Checkbox()
mischte
quelle
6

Eine weitere Option ist die Kombination von Funktionen aus den gängigsten Paketen.

Am beliebtesten sind require-dirkeine Optionen zum Filtern der Dateien / Verzeichnisse und keine mapFunktion (siehe unten), es wird jedoch ein kleiner Trick verwendet, um den aktuellen Pfad des Moduls zu finden.

Zweitens nach Popularität require-allhat Regexp Filterung und Vorverarbeitung, aber es fehlt ein relativer Pfad, so dass Sie verwenden müssen __dirname(dies hat Vor- und Nachteile) wie:

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

Erwähnt hier require-indexist ziemlich minimalistisch.

Mit mapkönnen Sie einige Vorverarbeitungen durchführen, z. B. Objekte erstellen und Konfigurationswerte übergeben (vorausgesetzt, Module unterhalb der Exportkonstruktoren):

// 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
quelle
5

Ich weiß, dass diese Frage mindestens 5 Jahre alt ist und die gegebenen Antworten gut sind, aber ich wollte etwas Stärkeres für Express, also habe ich das express-map2Paket für npm erstellt. Ich wollte es einfach benennen express-map, aber die Leute bei Yahoo haben bereits ein Paket mit diesem Namen, also musste ich mein Paket umbenennen.

1. Grundgebrauch:

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

Controller-Nutzung:

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

};

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

    foo: function(req,res){

    },

    bar: function(req,res){

    }

};

2. Erweiterte Verwendung mit Präfixen:

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

Wie Sie sehen, spart dies eine Menge Zeit und macht das Routing Ihrer Anwendung kinderleicht zu schreiben, zu warten und zu verstehen. Es unterstützt alle http-Verben, die Unterstützung ausdrücken, sowie die speziellen.all() Methode.

r3wt
quelle
3

Ein Modul, das ich für diesen genauen Anwendungsfall verwendet habe, ist require-all .

Es erfordert rekursiv alle Dateien in einem bestimmten Verzeichnis und seinen Unterverzeichnissen, solange sie nicht mit dem übereinstimmen excludeDirs Eigenschaft .

Außerdem können Sie einen Dateifilter angeben und die Schlüssel des zurückgegebenen Hash aus den Dateinamen ableiten.

Thorsten Lorenz
quelle
2

Ich verwende Knotenmodule Copy-to-Modul eine einzelne Datei zu erstellen , um alle Dateien in unserem NodeJS-basierten System erfordern.

Der Code für unsere Dienstprogrammdatei sieht folgendermaßen aus:

/**
 * Module dependencies.
 */

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

In allen Dateien werden die meisten Funktionen wie folgt als Exporte geschrieben:

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

Um eine Funktion aus einer Datei zu verwenden, rufen Sie einfach Folgendes auf:

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

var response = utility.function2(); // or whatever the name of the function is
Scottnath
quelle
2

Erweiterung dieser glob Lösung. Tun Sie dies, wenn Sie alle Module aus einem Verzeichnis in ein anderes index.jsimportieren und dieses dann index.jsin einen anderen Teil der Anwendung importieren möchten . Beachten Sie, dass Vorlagenliterale von der vom Stackoverflow verwendeten Hervorhebungs-Engine nicht unterstützt werden, sodass der Code hier möglicherweise seltsam aussieht.

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;

Vollständiges Beispiel

Verzeichnisaufbau

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 / unerwartete.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';

Aus dem Projekt mit glob installiertem ausführennode example.js

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

Kann verwenden: https://www.npmjs.com/package/require-file-directory

  • Benötigen Sie ausgewählte Dateien nur mit Namen oder alle Dateien.
  • Keine Notwendigkeit eines absoluten Pfades.
  • Einfach zu verstehen und zu bedienen.
Mayank Soni
quelle
2
Willkommen bei SO. Bitte lesen Sie diese Anleitung, um eine qualitativ hochwertige Antwort zu erhalten.
thewaywewere
1

Benötigen Sie alle Dateien aus dem routesOrdner und wenden Sie sie als Middleware an. Keine externen Module erforderlich.

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

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

Mit dieser Funktion können Sie ein ganzes Verzeichnis benötigen.

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
quelle
-2

Wenn Sie alle Dateien von * .js in das Verzeichnisbeispiel aufnehmen ("app / lib / *. Js"):

Im Verzeichnis app / lib

example.js:

module.exports = function (example) { }

Beispiel-2.js:

module.exports = function (example2) { }

In der Verzeichnis-App erstellen Sie index.js

index.js:

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