requireJS 整个文件夹

发布于 2024-11-04 20:44:04 字数 193 浏览 5 评论 0 原文

是否可以使用 requireJS“请求”整个文件夹。

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

Is it possible to "require" an entire folder using requireJS.

For example, I have a behaviors folder with a ton of behavior js files. I'd really like to be able to simply use require(['behaviors/*'], function() {...}); to load everything in that folder rather than having to keep that list up to date. Once compressed and optimized I'd have all those files lump together, but for development it's easier to work with them individually.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

源来凯始玺欢你 2024-11-11 20:44:04

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

javascript in browser has no filesystem access and so it can't scan a directory for files. If you are building your app in a scripting language like php or ruby you could write a script that scans the directory and adds the file names to the require() call.

ぽ尐不点ル 2024-11-11 20:44:04

我不知道我是否可以再推荐这种方法。我认为更明确的方法是手动“要求”/“导出”您需要的功能。我认为例外的是,如果您有要导出的文件的“命名空间”,请参见下面的“Babel 和 ES6 模块导入声明(export-namespace-from)”或参见下面的“Babel 和 ES6 模块导入声明”。

这些解决方案还假设您有一个有意义的文件结构 - 其中文件名成为“require”* 定义的一部分。

但是,如果您仍然需要执行此操作,有一些现有的工具和方法可能会提供您正在寻找的行为。


可能的解决方案

Babel 和 ES6 模块导入声明 (plugin-export-namespace-from)

  1. 设置为 符合 ES6
  2. 您需要更新您的 .babelrc 文件以包含 babel-plugin-proposal-export-namespace-from
  3. 通过编写如下语法来使用导出命名空间插件:

common/index.js

export * from './common/a'; // export const a = false;
export * from './common/b'; // export const b = true;

ma​​in.js

import { a, b } from './common';

console.log(a); // false
console.log(b); // true

Babel 和 ES6 模块导入声明(插件通配符)

  1. 进行ES6 兼容的设置。
  2. 您需要更新您的 .babelrc 文件以包含 babel-plugin-wildcard
  3. 通过编写如下语法来使用通配符命名空间插件:

ma​​in.js

import { a, b } from './common/*'; // imports './common/a.js' and './common/b.js'

console.log(a); // false
console.log(b); // true

RequireJS (Now Outdated)

  1. 下载并安装 require-wild npm install require-wild
  2. 配置声明如下,
    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']);
  1. 然后运行 ​​grunt 任务。将生成您的文件。修改您的设置以加载 namespaces.js

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

  1. 现在允许 src< 下的模块/code> 使用依赖项全局模式匹配。

require(['行为/**/*'], 函数(行为) { }

I don't know if I can recommend this approach anymore. I think the more explicit way to do this is by manually "requiring"/"exporting" the functionality you need. The exception I think is if you have a "namespace" of files that you want exported see below "Babel and ES6 Module Import Declarations (export-namespace-from) or see below "Babel and ES6 Module Import Declarations.

These solutions also assume that you have a meaningful file structure - where file names become part of that "require" * definition.

However, if you still need to do this there are a few existing tools and methods that might provide the behavior that you're looking for.


Possible Solutions

Babel and ES6 Module Import Declarations (plugin-export-namespace-from)

  1. Have a setup that is ES6 compliant.
  2. You need to update your .babelrc file to include babel-plugin-proposal-export-namespace-from.
  3. Use export namespace plugin by writing syntax like the following:

common/index.js

export * from './common/a'; // export const a = false;
export * from './common/b'; // export const b = true;

main.js

import { a, b } from './common';

console.log(a); // false
console.log(b); // true

Babel and ES6 Module Import Declarations (plugin-wildcard)

  1. Have a setup that is ES6 compliant.
  2. You need to update your .babelrc file to include babel-plugin-wildcard.
  3. Use wildcard namespace plugin by writing syntax like the following:

main.js

import { a, b } from './common/*'; // imports './common/a.js' and './common/b.js'

console.log(a); // false
console.log(b); // true

RequireJS (Now Outdated)

  1. Download and install require-wild npm install require-wild
  2. Configure the declaration as follows
    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']);
  1. Then run the grunt task. Your file will be generated. Modify your setup to load namespaces.js

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

  1. This now allows modules under src to use dependencies glob pattern matching.

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

标点 2024-11-11 20:44:04

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

对于此解决方案,您需要 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
我的目录/ThirdJavascriptFile

  • 我的脚本有问题!最后多加一个“”,这会搞乱一切!确保在 directoryContents.txt 末尾删除多余的空间

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

  • 执行“GET”请求来检索文本
  • 文件每个条目(由空格分隔),“需要”该文件:

.

$.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 文件列表,并需要该列表中的每个文件。

希望这有帮助!

I know this is old, but I'd like to share my solution:

For this solution you need JQuery

1) Create a bash script that will list all the js files in
"MyDirectory/", and save it to "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
  • File will look like this:

MyDirectory/FirstJavascriptFile MyDirectory/SecondJavascriptFile
MyDirectory/ThirdJavascriptFile

  • Problem with my script! Puts an extra " " at the end, that messes things up! Make sure to remove the excess space at the end of directoryContents.txt

2) Then in your Client side JS code:

  • do a "GET" request to retrieve the text file
  • For each entry (split by the space), 'require' that file:

.

$.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");

I was having a problem with this code not finishing before my other code, so Here's my extended answer:

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

What I ended up doing was everytime my Node server boots, it will run the bash script, populating directoryContents.txt. Then My client side just reads directoryContents.txt for the list of files, and requires each in that list.

Hope this helps!

悸初 2024-11-11 20:44:04

实际上没有一种方法可以在概念上动态执行此操作(据我所知)。

不过,有一些解决方法:

使用 gruntconcat< /code> 然后只需要那个庞然大物...我知道,有点糟糕。

我认为更好的解决方案...使用如下所示的 require 层次结构:

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

请注意“主角function。这允许您在使用模块之前对其进行初始化,因此现在您可以传入“sandbox”——在本例中为 appglobals

实际上,您不会有 /js/controllers/index.js ...它可能应该类似于 /js/controllers/index/main.js 或 < code>/js/controllers/index/init.js 这样就有一个与 /js/controllers/init.js 相邻的目录(其同级目录)称为“index”。这将使您的模块可扩展到给定的接口——您可以简单地交换模块并保持接口相同。

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

There isn't really a way to do this conceptually on the fly (that I know of).

There's a few work arounds though:

Use grunt and concat and then just require that behemoth...I know, kinda sucky.

What I think is a better solution... use a require hierarchy like so:

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

Note that "protagonist" function. That allows you to initialize modules before their use, so now you can pass in a 'sandbox' -- in this case app and globals.

Realistically, you wouldn't have /js/controllers/index.js... It should probably be something like /js/controllers/index/main.js or /js/controllers/index/init.js so that there is a directory adjacent to (sibling of) /js/controllers/init.js called "index". This will make your modules scalable to a given interface -- you can simply swap modules out and keep your interface the same.

Hope this helps! Happy coding!

苍暮颜 2024-11-11 20:44:04

我写了一个库来解决这个问题。最终,其他人出现并改进了我的库,如下:

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

你可以将我的 lib 与 Gulp 或其他任何东西一起使用 - 它为你的项目生成元数据,并且 RequireJS 可以使用该元数据从文件系统中获取所需的文件。

使用这个库将生成一个看起来像这样的 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]
        }
    });

然后,您可以像这样在前端中 require 模块:

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

但是,正如您所看到的,这太冗长了,所以神奇的方法如下:

命名上面的依赖项和大家一样!

现在您可以这样做:

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

I wrote a library to solve this problem. Eventually someone else came along and improved my library, here it is:

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

You can use my lib with Gulp or whatever - it generates metadata for your project and RequireJS can use that metadata to require the desired files from the filesystem.

Using this lib will produce a RequireJS module that looks something like this:

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

You can then require modules in your front-end like so:

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

however, as you can see this is too verbose, so the magic way is like so:

name the dependency above as allViews!

now you can do:

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

There are two advantages to requiring directories whole:

(1) in production, with the r.js optimizer, you can point to one dependency (module A) and it can then easily trace all of A's dependencies that represent a entire directory

(2) in development, you can require whole directories up front and then use synchronous syntax to require dependencies because you know they have already been loaded

enjoy "RequireJS-Metagen"

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

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文