requireJS整个文件夹

时间:2011-05-05 05:17:01

标签: javascript requirejs

是否可以使用requireJS“需要”整个文件夹。

例如,我有一个行为文件夹,其中包含大量行为js文件。我真的希望能够简单地使用require(['behavior / *'],function(){...});加载该文件夹中的所有内容,而不是必须使该列表保持最新。一旦压缩和优化,我就会把所有这些文件放在一起,但是对于开发来说,单独使用它们会更容易。

5 个答案:

答案 0 :(得分:24)

浏览器中的javascript没有文件系统访问权限,因此无法扫描目录中的文件。如果您使用php或ruby等脚本语言构建应用程序,则可以编写一个扫描目录的脚本,并将文件名添加到require()调用中。

答案 1 :(得分:8)

虽然浏览器中的JavaScript不能(也不应该)看到文件系统,但我创建了一个Grunt任务,它将执行此操作。我现在还在努力在这里和那里触摸它,但欢迎你来看看。

https://npmjs.org/package/require-wild

npm install require-wild

在您的情况下,您所要做的就是设置任务的设置

grunt.initConfig({
    requireWild: {
        app: {
            // Input files to look for wildcards (require|define)
            src: ["./**/*.js"], 

            // Output file contains generated namespace modules
            dest: "./namespaces.js", 

            // Load your require config file used to find baseUrl - optional
            options: { requireConfigFile: "./main.js" }
        }
    }
}); 

grunt.loadNpmTasks("require-wild");

grunt.registerTask('default', ['requireWild']);

然后运行grunt任务。您的文件将被生成。修改您的main.js以加载namespaces.js

require(['namespaces'], function () { ... });

因此现在允许src下的模块使用与grunt的glob模式匹配的依赖关系。

require(['behaviors/**/*'], function (behaviors) { }

这种意识形态假设您有一个有意义的文件结构。

答案 2 :(得分:5)

我知道这已经过时了,但我想分享我的解决方案:

对于此解决方案,您需要JQuery

1)创建一个 bash脚本列出所有js文件     “MyDirectory /”,将其保存到“directoryContents.txt”

#!/bin/bash
  #Find all the files in that directory...
  for file in $( find MyDirectory/ -type f -name "*.js" )
        do
          fileClean=${file%.js} #Must remove .js from the end!
          echo -n "$fileClean " >> MyDirectory/directoryContents.txt
        done
  • 文件将如下所示:
  

MyDirectory / FirstJavascriptFile MyDirectory / SecondJavascriptFile   mydirectory中/ ThirdJavascriptFile

  • 我的剧本出现问题!在最后增加一个“”,这会让事情变得混乱!确保在 directoryContents.txt
  • 的末尾删除多余空格

2)然后在你的客户端JS代码:

  • 执行“GET”请求以检索文本文件
  • 对于每个条目(按空格分割),'require'该文件:

$.get( "MyDirectory/directoryContents.txt", {}, function( data ) {
    var allJsFilesInFolder = data.split(" ");
    for(var a=0; a<allJsFilesInFolder.length; a++)
    {
        require([allJsFilesInFolder[a]], function(jsConfig) 
        {
            //Done loading this one file
        });
    }
}, "text");

我遇到的问题是这段代码没有在我的其他代码之前完成,所以这是我的扩展答案:

define([''], function() {

return {

    createTestMenu: function() 
    {
        this.loadAllJSFiles(function(){
            //Here ALL those files you need are loaded!
        });
    },

    loadAllJSFiles: function(callback)
    {   
        $.get( "MyDirectory/directoryContents.txt", {}, function( data ) {
            var allJsFilesInFolder = data.split(" ");
            var currentFileNum = 0;
            for(var a=0; a<allJsFilesInFolder.length; a++)
            {
                require([allJsFilesInFolder[a]], function(jsConfig) 
                {
                    currentFileNum++;
                    //If it's the last file that needs to be loaded, run the callback.
                    if (currentFileNum==allJsFilesInFolder.length)
                    {
                        console.log("Done loading all configuration files.");
                        if (typeof callback != "undefined"){callback();}
                    }
                });
            }
        }, "text");
    }
}
});

我最终做的是每次我的Node服务器启动时,它都会运行bash脚本,填充directoryContents.txt。然后我的客户端只读取directoryContents.txt作为文件列表,并要求该列表中的每一个。

希望这有帮助!

答案 3 :(得分:1)

实际上没有办法在概念上做到这一点(我知道)。

虽然有一些解决方法:

使用gruntconcat然后只需要那个庞然大物......我知道,有点太糟糕了。

我认为更好的解决方案......使用需要的层次结构:

require('/js/controllers/init', function(ctrls){
    ctrls(app, globals);
});

// /js/controllers/init.js
define('js/controllers/index', 'js/controllers/posts', function(index, posts){
    return function protagonist(app, globals){
        var indexModule = index(app, globals);
        var indexModule = posts(app, globals);

        return app || someModule;
    };
});

// /js/controllers/index.js
define('js/controllers/index', 'js/controllers/posts', function(index, posts){
    return function protagonist(app, globals){
        function method1(){}
        function method2(){}

        return {
           m1: method1,
           m2: method2
        };
    };
});

请注意“protagonistfunction。这允许您在使用之前初始化模块,因此现在您可以传递“sandbox” - 在这种情况下appglobals

实际上,你不会有/js/controllers/index.js ......它可能应该是/js/controllers/index/main.js/js/controllers/index/init.js,因此有一个目录(兄弟){{1}称为“索引”。这将使您的模块可以扩展到给定的接口 - 您可以简单地交换模块并保持您的接口相同。

希望这有帮助!快乐的编码!

答案 4 :(得分:1)

我写了一个库来解决这个问题。最终有其他人出现并改进了我的图书馆,这里是:

https://github.com/smartprocure/directory-metagen

您可以将我的lib与Gulp一起使用 - 它会为您的项目生成元数据,而RequireJS可以使用该元数据来从文件系统中获取所需的文件。

使用此lib将生成一个如下所示的RequireJS模块:

define(
    [
        "text!app/templates/dashboardTemplate.ejs",
        "text!app/templates/fluxCartTemplate.ejs",
        "text!app/templates/footerTemplate.ejs",
        "text!app/templates/getAllTemplate.ejs",
        "text!app/templates/headerTemplate.ejs",
        "text!app/templates/homeTemplate.ejs",
        "text!app/templates/indexTemplate.ejs",
        "text!app/templates/jobsTemplate.ejs",
        "text!app/templates/loginTemplate.ejs",
        "text!app/templates/overviewTemplate.ejs",
        "text!app/templates/pictureTemplate.ejs",
        "text!app/templates/portalTemplate.ejs",
        "text!app/templates/registeredUsersTemplate.ejs",
        "text!app/templates/userProfileTemplate.ejs"
    ],
    function(){

        return {

            "templates/dashboardTemplate.ejs": arguments[0],
            "templates/fluxCartTemplate.ejs": arguments[1],
            "templates/footerTemplate.ejs": arguments[2],
            "templates/getAllTemplate.ejs": arguments[3],
            "templates/headerTemplate.ejs": arguments[4],
            "templates/homeTemplate.ejs": arguments[5],
            "templates/indexTemplate.ejs": arguments[6],
            "templates/jobsTemplate.ejs": arguments[7],
            "templates/loginTemplate.ejs": arguments[8],
            "templates/overviewTemplate.ejs": arguments[9],
            "templates/pictureTemplate.ejs": arguments[10],
            "templates/portalTemplate.ejs": arguments[11],
            "templates/registeredUsersTemplate.ejs": arguments[12],
            "templates/userProfileTemplate.ejs": arguments[13]
        }
    });

然后您可以在前端需要模块,如下所示:

var footerView = require("app/js/jsx/standardViews/footerView");

但是,你可以看到这太冗长了,所以神奇的方式是这样的:

将上面的依赖项命名为allViews!

现在你可以这样做:

var allViews = require('allViews');
var footerView = allViews['standardViews/footerView'];

要求整个目录有两个好处:

(1)在生产中,使用r.js优化器,您可以指向一个依赖项(模块A),然后它可以轻松跟踪表示整个目录的所有A的依赖项

(2)在开发中,你可以预先要求整个目录,然后使用同步语法来要求依赖,因为你知道它们已经被加载了

享受“RequireJS-Metagen”

https://github.com/smartprocure/directory-metagen

https://www.npmjs.com/package/requirejs-metagen

https://github.com/ORESoftware/requirejs-metagen