【问题标题】:node.js require all files in a folder?node.js 需要一个文件夹中的所有文件?
【发布时间】:2011-07-18 21:45:41
【问题描述】:

如何要求 node.js 中文件夹中的所有文件?

需要类似的东西:

files.forEach(function (v,k){
  // require routes
  require('./routes/'+v);
}};

【问题讨论】:

标签: javascript node.js directory require


【解决方案1】:

当 require 给出一个文件夹的路径时,它会在那个文件夹中寻找一个 index.js 文件;如果有,它会使用它,如果没有,它会失败。

创建 index.js 文件然后分配所有“模块”然后简单地要求它可能最有意义(如果您可以控制文件夹)。

yourfile.js

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

index.js

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

如果您不知道文件名,您应该编写某种加载器。

加载器的工作示例:

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

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

// Continue application logic here

【讨论】:

  • 补充一点说明:当require 被指定一个文件夹的路径时,它会在那个文件夹中寻找一个index.js;如果有,它会使用它,如果没有,它会失败。请参阅github.com/christkv/node-mongodb-native 以了解此示例:根目录中有一个index.js,需要./lib/mongodb,这是一个目录; ./lib/mongodb/index.js' 使该目录中的所有其他内容都可用。
  • require 是一个同步函数,因此回调没有任何好处。我会改用 fs.readdirSync。
  • 谢谢,今天遇到了同样的问题,想“为什么没有 require('./routes/*')?”。
  • @RobertMartin 当您不需要任何导出的句柄时,它很有用;例如,如果我只想将 Express 应用程序实例传递给一组绑定路由的文件。
  • @TrevorBurnham 补充一下,可以通过package.json在这个目录下修改一个目录的主文件(即index.js)文件。像这样:{main: './lib/my-custom-main-file.js'}
【解决方案2】:

我建议使用glob 来完成该任务。

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

glob.sync( './routes/**/*.js' ).forEach( function( file ) {
  require( path.resolve( file ) );
});

【讨论】:

  • 每个人都应该使用这个答案;)
  • 最佳答案!比所有其他选项更容易,尤其是对于包含需要包含的文件的递归子文件夹。
  • glob?你的意思是glob-savior-of-the-nodejs-race。最佳答案。
  • 它保存到哪些变量? var x = require('x') 在这种情况下var x 是什么?
  • 使用 map() 保存链接: const routes = glob.sync('./routes/**/*.js').map(file => require( path.resolve( file ) ));
【解决方案3】:

基于@tbranyen 的解决方案,我创建了一个index.js 文件,该文件在当前文件夹下加载任意javascripts 作为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);
  }
});

然后你可以从其他任何地方require这个目录。

【讨论】:

  • 我知道这已经有一年多了,但实际上你也可以需要 JSON 文件,所以也许像 /\.js(on)?$/ 这样的东西会更好。 !== null也不是多余的吗?
【解决方案4】:

另一种选择是使用包require-dir,它可以让您执行以下操作。它也支持递归。

var requireDir = require('require-dir');
var dir = requireDir('./path/to/dir');

【讨论】:

  • +1 表示require-dir,因为它会自动排除调用文件(索引)并默认为当前目录。完美。
  • 在 npm 中还有一些类似的包:require-all、require-directory、require-dir 等。至少在 2015 年 7 月,下载次数最多的似乎是全部要求。
  • require-dir 现在是下载次数最多的(但值得注意的是,在撰写本文时它不支持文件排除)
  • 在肖恩发表上述评论三年后,require-dir 添加了一个filter 选项。
【解决方案5】:

我有一个文件夹/字段,里面满是文件,每个文件都有一个类,例如:

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

将这个放到 fields/index.js 中以导出每个类:

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

这使得模块的行为更像它们在 Python 中的行为:

var text = new Fields.Text()
var checkbox = new Fields.Checkbox()

【讨论】:

    【解决方案6】:

    另一种选择是require-dir-all 结合最流行软件包的功能。

    最流行的require-dir 没有过滤文件/目录的选项,也没有map 功能(见下文),但使用小技巧来查找模块的当前路径。

    其次,require-all 有正则表达式过滤和预处理,但缺少相对路径,所以你需要使用__dirname(这有优缺点)比如:

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

    这里提到的require-index 非常简约。

    使用map,您可以进行一些预处理,例如创建对象并传递配置值(假设模块位于导出构造函数下方):

    // 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`.
    

    【讨论】:

      【解决方案7】:

      我知道这个问题已经有 5 年以上的历史了,给出的答案很好,但我想要一些更强大的 express,所以我为 npm 创建了 express-map2 包。我打算将其命名为 express-map,但是 yahoo 的 people 已经有一个使用该名称的包,所以我不得不重命名我的包。

      1.基本用法:

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

      控制器使用:

      //single function
      module.exports = function(req,res){
      
      };
      
      //export an object with multiple functions.
      module.exports = {
      
          foo: function(req,res){
      
          },
      
          bar: function(req,res){
      
          }
      
      };
      

      2。高级用法,带前缀:

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

      如您所见,这节省了大量时间,并使您的应用程序的路由非常易于编写、维护和理解。它支持所有表示支持的http动词,以及特殊的.all()方法。

      【讨论】:

        【解决方案8】:

        扩展 this glob 解决方案。如果要将目录中的所有模块导入index.js,然后将index.js 导入应用程序的另一部分,请执行此操作。请注意,stackoverflow 使用的突出显示引擎不支持模板文字,因此此处的代码可能看起来很奇怪。

        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;
        

        完整示例

        目录结构

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

        从带有glob installed 的项目内部,运行node example.js

        $ node example.js
        foo ran
        bar run
        keepit ran unexpected
        foo ran
        bar run
        keepit ran unexpected
        

        【讨论】:

          【解决方案9】:

          我一直用于这个确切用例的一个模块是require-all

          它递归地要求给定目录及其子目录中的所有文件,只要它们不匹配 excludeDirs 属性。

          它还允许指定文件过滤器以及如何从文件名中派生返回哈希的键。

          【讨论】:

            【解决方案10】:

            需要routes 文件夹中的所有文件并作为中间件应用。无需外部模块。

            // require
            const path = require("path");
            const { readdirSync } = require("fs");
            
            // apply as middleware
            readdirSync("./routes").map((r) => app.use("/api", require("./routes/" + r)));
            

            【讨论】:

            • 但是为什么这里会请求path
            【解决方案11】:

            我正在使用node modules copy-to module 创建一个文件来要求我们基于 NodeJS 的系统中的所有文件。

            our utility file 的代码如下所示:

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

            在所有文件中,大多数函数都写为导出,如下所示:

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

            所以,要使用文件中的任何函数,您只需调用:

            var utility = require('./utility');
            
            var response = utility.function2(); // or whatever the name of the function is
            

            【讨论】:

              【解决方案12】:

              可以使用:https://www.npmjs.com/package/require-file-directory

              • 要求选定的文件仅具有名称或所有文件。
              • 不需要绝对路径。
              • 易于理解和使用。

              【讨论】:

              • 欢迎来到 SO。请阅读此how-to-answer 以提供高质量的答案。
              【解决方案13】:

              使用此功能,您可能需要一个完整的目录。

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

              【讨论】:

              • 对此答案的一个建议是,当前的正则表达式将匹配 "serverjslib.js" 之类的奇怪事物并将其转换为 "servelib",这会破坏事物。注意服务器中的“r”是如何被切断的。那是因为您的正则表达式确实匹配“[任何单个字符] js”。显然,模块名称很糟糕,但对于 "express-json.js""load-json-file.js""parse-json.js" 之类的名称也是如此,将名称分别更改为 "expresson""loadon-file""parseon"。这可以通过将您的正则表达式更改为 /\.js$/ 来解决,仅匹配末尾的文字点和 js
              【解决方案14】:

              使用此代码在您的文件夹中创建一个 index.js 文件:

              const fs = require('fs')    
              const files = fs.readdirSync('./routes')
              for (const file of files) {
                require('./'+file)
              }
              

              然后你可以简单地用require("./routes")加载所有文件夹

              【讨论】:

                【解决方案15】:

                如果您在目录示例(“app/lib/*.js”)中包含所有 *.js 文件:

                在目录 app/lib

                example.js:

                module.exports = function (example) { }
                

                example-2.js:

                module.exports = function (example2) { }
                

                在目录应用中创建 index.js

                index.js:

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

                【讨论】:

                  猜你喜欢
                  • 2020-08-08
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-02-26
                  • 2018-08-10
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多