node.js requiere todos los archivos en una carpeta?

Respuestas:

515

Cuando require recibe la ruta de una carpeta, buscará un archivo index.js en esa carpeta; si hay uno, lo usa, y si no lo hay, falla.

Probablemente tendría más sentido (si tiene control sobre la carpeta) crear un archivo index.js y luego asignar todos los "módulos" y luego simplemente requerirlo.

yourfile.js

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

index.js

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

Si no conoce los nombres de los archivos, debe escribir algún tipo de cargador.

Ejemplo de trabajo de un cargador:

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

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

// Continue application logic here
tbranyen
fuente
152
Para agregar alguna aclaración: cuando requirese le da la ruta de una carpeta, buscará una index.jsen esa carpeta; si hay uno, lo usa, y si no lo hay, falla. Consulte github.com/christkv/node-mongodb-native para ver un ejemplo real de esto: hay un index.jsdirectorio raíz que requiere ./lib/mongodb, un directorio; ./lib/mongodb/index.js'hace que todo lo demás en ese directorio esté disponible.
Trevor Burnham
22
requirees una función síncrona, por lo que no hay beneficios de la devolución de llamada. En su lugar, usaría fs.readdirSync.
Rafał Sobota
44
Gracias, me encontré con este mismo problema hoy y pensé "¿por qué no hay un requerimiento ('./ rutas / *')?".
Richard Clayton
3
@RobertMartin es útil cuando no necesita un identificador para nada exportado; por ejemplo, si solo quisiera pasar una instancia de la aplicación Express a un conjunto de archivos que enlazarían rutas.
Richard Clayton
2
@TrevorBurnham Para agregar, el archivo del archivo principal (es decir, index.js) de un directorio se puede cambiar package.jsonen este directorio. De este modo:{main: './lib/my-custom-main-file.js'}
antitóxica
187

Recomiendo usar glob para lograr esa tarea.

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

glob.sync( './routes/**/*.js' ).forEach( function( file ) {
  require( path.resolve( file ) );
});
Diogo Cardoso
fuente
12
Todos deberían usar esta respuesta;)
Jamie Hutber
2
¡La mejor respuesta! Más fácil que todas las otras opciones, especialmente para las carpetas secundarias recursivas que tienen archivos que debe incluir.
ngDeveloper
1
Se recomienda el bloqueo global debido al control general que tiene sobre los conjuntos de criterios de especificación de archivos que puede especificar.
stephenwil
66
glob? que quiere decir glob-savior-of-the-nodejs-race. La mejor respuesta.
profundización
3
Use map () para guardar enlaces: const routes = glob.sync ('./ routes / ** / *. Js'). Map (file => require (path.resolve (file)));
lexa-b
71

Basado en la solución de @ tbranyen, creo un index.jsarchivo que carga javascripts arbitrarios en la carpeta actual como parte de 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);
  }
});

Entonces puede requireeste directorio desde cualquier otro lugar.

Greg Wang
fuente
55
Sé que esto tiene más de un año, pero en realidad también puede requerir archivos JSON, por lo que tal vez algo así /\.js(on)?$/sería mejor. ¿Tampoco es !== nullredundante?
59

Otra opción es usar el paquete require-dir que le permite hacer lo siguiente. Es compatible con la recursividad también.

var requireDir = require('require-dir');
var dir = requireDir('./path/to/dir');
studgeek
fuente
3
+1 require-dirporque excluye automáticamente el archivo de llamada (índice) y por defecto es el directorio actual. Perfecto.
biofractal
2
En npm hay algunos paquetes más similares: require-all, require-directory, require-dir y otros. El más descargado parece ser
obligatorio
require-dir ahora es el más descargado (pero notablemente no admite la exclusión de archivos al momento de escribir)
Sean Anderson
Tres años después del comentario de Sean anterior, require-diragregó una filteropción.
givemesnacks
7

Tengo una carpeta / campos llenos de archivos con una sola clase cada uno, por ejemplo:

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

Suelte esto en fields / index.js para exportar cada clase:

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

Esto hace que los módulos actúen más como lo harían en Python:

var text = new Fields.Text()
var checkbox = new Fields.Checkbox()
sangrado
fuente
6

Una opción más es require-dir-all combinando características de los paquetes más populares.

El más popular require-dirno tiene opciones para filtrar los archivos / directorios y no tiene mapfunción (ver más abajo), pero utiliza un pequeño truco para encontrar la ruta actual del módulo.

En segundo lugar, por popularidad require-alltiene el filtrado y el preprocesamiento de expresiones regulares, pero carece de una ruta relativa, por lo que debe usar __dirname(esto tiene ventajas y desventajas) como:

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

Mencionado aquí require-indexes bastante minimalista.

Con mapusted puede hacer un preprocesamiento, como crear objetos y pasar valores de configuración (suponiendo que los módulos debajo de los constructores de exportaciones):

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

Sé que esta pregunta tiene más de 5 años y las respuestas dadas son buenas, pero quería algo un poco más potente para express, así que creé el express-map2paquete para npm. Iba a nombrarlo simplemente express-map, sin embargo, las personas en Yahoo ya tienen un paquete con ese nombre, así que tuve que cambiar el nombre de mi paquete.

1. uso básico:

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

uso del controlador:

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

};

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

    foo: function(req,res){

    },

    bar: function(req,res){

    }

};

2. uso avanzado, con prefijos:

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

Como puede ver, esto ahorra un montón de tiempo y hace que el enrutamiento de su aplicación sea fácil de escribir, mantener y comprender. Es compatible con todos los verbos http que expresan soportes, así como con el .all()método especial .

r3wt
fuente
3

Un módulo que he estado usando para este caso de uso exacto es require-all .

Requiere recursivamente todos los archivos en un directorio dado y sus subdirectorios siempre que no coincidan con la excludeDirspropiedad.

También permite especificar un filtro de archivo y cómo derivar las claves del hash devuelto a partir de los nombres de archivo.

Thorsten Lorenz
fuente
2

Estoy usando módulos de nodo de copia para crear un solo archivo para requerir todos los archivos en nuestro sistema basado en NodeJS.

El código para nuestro archivo de utilidad se ve así:

/**
 * Module dependencies.
 */

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

En todos los archivos, la mayoría de las funciones se escriben como exportaciones, así:

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

Entonces, para usar cualquier función de un archivo, simplemente llame:

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

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

Ampliando esta glob solución. Haga esto si desea importar todos los módulos de un directorio index.jsy luego importarlo index.jsen otra parte de la aplicación. Tenga en cuenta que los literales de plantilla no son compatibles con el motor de resaltado utilizado por stackoverflow, por lo que el código puede parecer extraño aquí.

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;

Ejemplo completo

Estructura de directorios

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

Desde dentro del proyecto con glob instalado , ejecutenode example.js

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

Requerir todos los archivos de la routescarpeta y aplicarlos como middleware. No se necesitan módulos externos.

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

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

Usando esta función puede requerir un directorio completo.

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

Si incluye todos los archivos de * .js en el ejemplo de directorio ("app / lib / *. Js"):

En directorio app / lib

ejemplo.js:

module.exports = function (example) { }

ejemplo-2.js:

module.exports = function (example2) { }

En la aplicación de directorio, cree index.js

index.js:

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